edu.kit.ipd.sonar.client.jsxGraph.JSXBoard.java Source code

Java tutorial

Introduction

Here is the source code for edu.kit.ipd.sonar.client.jsxGraph.JSXBoard.java

Source

/**
 * This file is part of Sonar.
 *
 * Sonar is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, version 2 of the License.
 *
 * Sonar is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Sonar.  If not, see <http://www.gnu.org/licenses/>.
 */
package edu.kit.ipd.sonar.client.jsxGraph;

import edu.kit.ipd.sonar.client.Color;
import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import java.util.ArrayList;

/**
 * This class wraps around the JSXGraph javascript class JSXBoard.
 */
public class JSXBoard {

    /** The "resulution" of our jsxboard. */
    protected static final int SCALA = 1000;
    /** The javascriptobject jsx-board to make it accessible via java. */
    private JavaScriptObject jsxboard;
    /** The javascriptobject object for updating the tooltips. */
    private JavaScriptObject infoUpdater;
    /** List of all created points. */
    private ArrayList<JSXPoint> points = new ArrayList<JSXPoint>();
    /** List of all created lines. */
    private ArrayList<JSXLine> lines = new ArrayList<JSXLine>();
    /** List of all created arrows. */
    private ArrayList<JSXArrow> arrows = new ArrayList<JSXArrow>();
    /** The DOM id of our jsxboard. */
    private String domElementID;

    /**
     * Create a new JSXBoard.
     *
     * It will be inserted into the dom at the given id.
     *
     * @param newDomElementID The domid under which the element is be inserted.
     */
    JSXBoard(final String newDomElementID) {
        if (newDomElementID == null || newDomElementID == "") {
            throw new IllegalArgumentException("newDomElementID must not be " + "null.");
        }
        int top = DOM.getElementById(newDomElementID).getAbsoluteTop();
        int left = DOM.getElementById(newDomElementID).getAbsoluteLeft();
        jsxCreateBoard(newDomElementID, top, left);

        domElementID = newDomElementID;
    }

    /**
     * No-argument constructor for testing.
     * We need this constructor, because we can't test JSXPoint etc. otherwise.
     * The Problem ist, that JSXPoint etc. need a JSXBoard in their constructor
     * and we can't instanciate one with the domElementID because all calls to
     * the dom fail in unittests.
     * TODO: DO THIS BETTER IF POSSIBLE
     */
    JSXBoard() {
    };

    /**
     * Abstraction of an arrow from JSXGraph.
     *
     * @param p1 the first point of the arrow
     * @param p2 the second point of the arrow
     * @param width the width of the arrow
     * @param tooltip the tooltip of the arrow
     *
     * @return reference of the created line
     */
    JSXArrow createJSXArrow(final JSXPoint p1, final JSXPoint p2, final int width, final String tooltip) {
        JSXArrow ret = new JSXArrow(this);
        ret.setPoint1(p1);
        ret.setPoint2(p2);
        ret.setWidth(width);
        ret.setTooltip(tooltip);
        arrows.add(ret);

        return ret;
    }

    /**
     * Abstraction of a line from JSXGraph.
     *
     * @param p1 the first point of the line
     * @param p2 the second point of the line
     * @param width the width of the line
     * @param tooltip the tooltip of the line
     *
     * @return reference of the created line
     */
    JSXLine createJSXLine(final JSXPoint p1, final JSXPoint p2, final int width, final String tooltip) {
        JSXLine ret = new JSXLine(this);
        ret.setPoint1(p1);
        ret.setPoint2(p2);
        ret.setWidth(width);
        ret.setTooltip(tooltip);
        lines.add(ret);

        return ret;
    }

    /**
     * Abstraction of a point from JSXGraph.
     *
     * @param x the X coordinate
     * @param y the Y coordinate
     * @param color the color of the point
     * @param tooltip the tooltip of the point
     * @param radius the radius of the point
     *
     * @return Reference to of the created point
     */
    JSXPoint createJSXPoint(final double x, final double y, final Color color, final String tooltip,
            final int radius) {
        JSXPoint ret = new JSXPoint(this);
        ret.setX(x);
        ret.setY(y);
        ret.setColor(color);
        ret.setTooltip(tooltip);
        ret.setRadius(radius);
        points.add(ret);

        return ret;
    }

    /**
     * Resets all Elements drawn on the JSXBoard.
     */
    void reset() {
        while (lines.size() > 0) {
            removeJSXLine(lines.get(0));
        }

        while (points.size() > 0) {
            removeJSXPoint(points.get(0));
        }

        this.resetInfo();
    }

    /**
     * Resets the infoboxes.
     * This function is mainlyy useful, if you alt-tab out auf sonar
     * or on logout, to hide the infos from previous users.
     */
    void resetInfo() {
        this.jsResetInfo();
    }

    /**
     * Removes the given arrow from the JSXBoard.
     *
     * @param a the arrow to remove
     */
    void removeJSXArrow(final JSXArrow a) {
        int index = arrows.indexOf(a);
        if (index != -1) {
            if (a.getJsxArrow() != null) {
                jsxRemoveObject(a.getJsxArrow());
            } else {
                GWT.log("WARNING: jsxline == null on removeJSXArrow", null);
            }
            arrows.remove(index);
        }
    }

    /**
     * Removes the given point from the JSXBoard.
     *
     * @param p the point to remove
     */
    void removeJSXPoint(final JSXPoint p) {
        int index = points.indexOf(p);
        if (index != -1) {
            if (p.getJsxPoint() != null) {
                jsxRemoveObject(p.getJsxPoint());
            } else {
                GWT.log("WARNING: jsxpoint == null on removeJSXLine", null);
            }
            points.remove(index);
        }
    }

    /**
     * Removes the given line from the JSXBoard.
     *
     * @param l the line to remove
     */
    void removeJSXLine(final JSXLine l) {
        int index = lines.indexOf(l);
        if (index != -1) {
            if (l.getJsxLine() != null) {
                jsxRemoveObject(l.getJsxLine());
            } else {
                GWT.log("WARNING: jsxline == null on removeJSXLine", null);
            }
            lines.remove(index);
        }
    }

    /**
     * Start the autoupdate function of the JSXBoard.
     */
    void startUpdate() {
        jsxSetUpdate(true);
    }

    /**
     * Stops the autoupdate function of the JSXBoard.
     */
    void stopUpdate() {
        jsxSetUpdate(false);
    }

    /**
     * Returns the pixel height of the jsxboard.
     *
     * @return the pixel height
     */
    int getHeight() {
        Element b = DOM.getElementById(domElementID);
        if (b != null) {
            return b.getClientHeight();
        }
        GWT.log("board element not find in getHeight", null);
        return 0;
    }

    /**
     * Returns the pixel width of the jsxboard.
     *
     * @return the pixel width
     */
    int getWidth() {
        Element b = DOM.getElementById(domElementID);
        if (b != null) {
            return b.getClientWidth();
        }
        GWT.log("board element not find in getWidth", null);
        return 0;
    }

    /**
     * Returns the wrapped jsxboard to classes within the package.
     *
     * @return the wrapped jsxboard
     */
    protected JavaScriptObject getJsxBoard() {
        return jsxboard;
    }

    /**
     * Wraps around the board-creation via JSNI.
     *
     * In this function, i remove the global jsxgraph license text,
     * because we don't want it.
     * Then we create the jsxboard in the given DOM-Element.
     * Later i override the highlight functions as suggested by jsxgraph to
     * display the tooltips.
     * Finally i wrap this board reference back into java to make it accessible
     * from within our app.
     *
     * @param domID the dom-element id
     * @param fixTop value of the jsxBoardContainer
     * @param fixLeft value of the jsxBoardContainer
     */
    private native void jsxCreateBoard(final String domID, final int fixTop, final int fixLeft) /*-{
                                                                                                $wnd.JXG.JSXGraph.licenseText = "";
                                                                                                    
                                                                                                var scala = @edu.kit.ipd.sonar.client.jsxGraph.JSXBoard::SCALA;
                                                                                                var nodetooltipid =
                                                                                                @edu.kit.ipd.sonar.client.jsxGraph.JSXGraphDrawer::NODE_TOOLTIP_ID;
                                                                                                var edgetooltipid =
                                                                                                @edu.kit.ipd.sonar.client.jsxGraph.JSXGraphDrawer::EDGE_TOOLTIP_ID;
                                                                                                    
                                                                                                var nodeInfobox = $wnd.document.getElementById(nodetooltipid);
                                                                                                var edgeInfobox = $wnd.document.getElementById(edgetooltipid);
                                                                                                    
                                                                                                var infoUpdater = new function(nodebox, edgebox) {
                                                                                                var self = this;
                                                                                                self.edgebox = edgebox;
                                                                                                self.nodebox = nodebox;
                                                                                                self.edgelist = new Array();
                                                                                                self.nodelist = new Array();
                                                                                                    
                                                                                                self.removeFromList = function(ar,elem) {
                                                                                                var i = 0;
                                                                                                for(var e in ar) {
                                                                                                if(ar[e].el === elem)
                                                                                                ar.splice(i,1);
                                                                                                i++;
                                                                                                }
                                                                                                }
                                                                                                    
                                                                                                self.addBR = function(string) {
                                                                                                if(string.substring(string.length - 4) != "<br>"
                                                                                                && string.substring(string.length - 5) != "<br/>"
                                                                                                && string.substring(string.length - 6) != "<br />")
                                                                                                string += "<br>";
                                                                                                return string;
                                                                                                }
                                                                                                    
                                                                                                this.addNodeinfo = function(newel, newtext) {
                                                                                                self.nodelist.push({el:newel, text:newtext});
                                                                                                self.nodeUpdate();
                                                                                                }
                                                                                                    
                                                                                                this.removeNodeinfo = function(el) {
                                                                                                self.removeFromList(self.nodelist, el);
                                                                                                self.nodeUpdate();
                                                                                                }
                                                                                                    
                                                                                                this.addEdgeinfo = function(newel, newtext) {
                                                                                                self.edgelist.push({el:newel, text:newtext});
                                                                                                self.edgeUpdate();
                                                                                                }
                                                                                                    
                                                                                                this.reset = function() {
                                                                                                self.nodelist = new Array();
                                                                                                self.edgelist = new Array();
                                                                                                self.nodebox.innerHTML = "";
                                                                                                self.edgebox.innerHTML = "";
                                                                                                }
                                                                                                    
                                                                                                this.removeEdgeinfo = function(el) {
                                                                                                self.removeFromList(self.edgelist, el);
                                                                                                self.edgeUpdate();
                                                                                                }
                                                                                                    
                                                                                                self.edgeUpdate = function() {
                                                                                                self.edgebox.innerHTML = "";
                                                                                                for(var el in self.edgelist) {
                                                                                                self.edgebox.innerHTML += self.addBR(
                                                                                                self.edgelist[el].text);
                                                                                                }
                                                                                                self.edgebox.innerHTML += "<br>";
                                                                                                }
                                                                                                    
                                                                                                self.nodeUpdate = function() {
                                                                                                self.nodebox.innerHTML = "";
                                                                                                for(var el in self.nodelist) {
                                                                                                self.nodebox.innerHTML += self.addBR(
                                                                                                self.nodelist[el].text);
                                                                                                }
                                                                                                self.nodebox.innerHTML += "<br>";
                                                                                                }
                                                                                                }(nodeInfobox, edgeInfobox);
                                                                                                    
                                                                                                this.@edu.kit.ipd.sonar.client.jsxGraph.JSXBoard::infoUpdater =
                                                                                                infoUpdater;
                                                                                                    
                                                                                                $wnd.JXG.Line.prototype.highlight = function(){
                                                                                                infoUpdater.addEdgeinfo(this, this.name);
                                                                                                this.board.renderer.highlight(this); // highlight the line
                                                                                                }
                                                                                                    
                                                                                                $wnd.JXG.Line.prototype.noHighlight = function(){
                                                                                                infoUpdater.removeEdgeinfo(this);
                                                                                                this.board.renderer.noHighlight(this); // dehighlight the line
                                                                                                }
                                                                                                    
                                                                                                $wnd.JXG.Point.prototype.highlight = function(){
                                                                                                infoUpdater.addNodeinfo(this, this.name);
                                                                                                this.board.renderer.highlight(this); // highlight the line
                                                                                                }
                                                                                                    
                                                                                                $wnd.JXG.Point.prototype.noHighlight = function(){
                                                                                                infoUpdater.removeNodeinfo(this);
                                                                                                this.board.renderer.noHighlight(this); // dehighlight the line
                                                                                                }
                                                                                                    
                                                                                                this.@edu.kit.ipd.sonar.client.jsxGraph.JSXBoard::jsxboard =
                                                                                                $wnd.JXG.JSXGraph.initBoard(domID,
                                                                                                {boundingbox:[-scala,scala,scala,-scala]});
                                                                                                }-*/;

    /**
     * This method is a native wrapper to delete a object from the jsxboard.
     *
     * @param obj the jsxobject to remove
     */
    private native void jsxRemoveObject(final JavaScriptObject obj) /*-{
                                                                    var board = this.@edu.kit.ipd.sonar.client.jsxGraph.JSXBoard::jsxboard;
                                                                    board.removeObject(obj);
                                                                    }-*/;

    /**
     * This method is a native wrapper to start and stop the jsxboard updating.
     *
     * @param update 1 to start updating, 0 to stop it
     */
    private native void jsxSetUpdate(final boolean update) /*-{
                                                           var board = this.@edu.kit.ipd.sonar.client.jsxGraph.JSXBoard::jsxboard;
                                                           if (update) {
                                                           board.unsuspendUpdate();
                                                           } else {
                                                           board.suspendUpdate();
                                                           }
                                                           }-*/;

    /**
     * This method resets the info texts in the infoupdater object.
     */
    private native void jsResetInfo() /*-{
                                      var infoUpdater =
                                      this.@edu.kit.ipd.sonar.client.jsxGraph.JSXBoard::infoUpdater;
                                      infoUpdater.reset();
                                      }-*/;
}