// Medusa is a graph viewer which allows interactive editing of networks
// (edges and nodes) and also connects to databases.
//
// Copyright (C) 2006 Sean Hooper
//
// This program 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; either version 2 of the License, or (at 
// your option) any later version.
//
// This program 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 this program; if not, write to the 
// Free Software Foundation, Inc., 
// 59 Temple Place, Suite 330, 
// Boston, MA 02111-1307 USA
package medusa.display;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.event.MouseEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.util.List;
import javax.swing.JOptionPane;
import medusa.*;
import medusa.dataio.DataLoader;
import medusa.georgios.Browser;
import medusa.graph.Edge;
import medusa.graph.Graph;
import medusa.graph.Node;

/**
 * Describe class EditableGraphPanel here.
 * This class extends BasicGraphPanel and allows mouse interactions,
 * and also data manipulation.
 * 
 * 
 * @author Sean Hooper
 * @version 1.0
 */
public class EditableGraphPanel extends BasicGraphPanel {
    //Image image=null;
    BufferedImage image = null;
    Image tempImage = null;
    // constructor
    /**
     * Constructor with settings
     * @param stringSettings settings
     */
    public EditableGraphPanel(MedusaSettings stringSettings) {
        super(stringSettings);
        initPopup();
        tryImage();
        initShow();
    //setBackground(Color.grey);
    }

    /**
     * Constructor with default settings
     */
    public EditableGraphPanel() {
        super();
        initPopup();
        tryImage();
        initShow();
    }

    private void tryImage() {
        try {
            setImage();
            tempImage = image;
        } catch (Exception e) {
        }
    }

    /**
     * Sets the default image
     * @throws java.io.IOException if default file
     */
    public void setImage() throws IOException {
        setImage("netview_default.png");
    }

    /**
     * Sets the background image
     * @param imageURL path to image
     * @throws java.io.IOException if image is not found or cannot be read.
     */
    public void setImage(final String imageURL)
            throws IOException {
        //System.out.println(imageURL);
        File imageFile = new File(imageURL);
        image = javax.imageio.ImageIO.read(imageFile);

    }

    /**
     *
     * @param myImage
     * @throws java.lang.InterruptedException
     */
    public void setImage(BufferedImage myImage) throws InterruptedException {
        image = myImage;
    //scaledCopy();
    }

    public void clearImage() {
        image = null;
    //System.out.println("image cleared");
    }

    /* -------------------------------------------------------------
     * -more overridden methods of BasicGraphPanel-------------------
     * -------------------------------------------------------------
     */
    public void drawBackgroundImage(Graphics2D g2d) {
        if (image == null) {
            return;
        }
        Dimension d = getPreferredSize();
        //System.out.println(d.width+" : "+d.height);
        g2d.drawImage(image, 0, 0, d.width, d.height, null);
    }

    public void paintEdge(Graphics2D g, Edge e) {
        if (!showEdges[e.getType() - 1]) {
            return;
        }
        super.paintEdge(g, e);

    }
    public boolean showBorder = true;

    public void setShowBorder(boolean show) {
        showBorder = show;
    }

    public void paintNet(Graphics2D g2d) {
        // if we have an image, paint it
        //drawBackgroundImage(g2d);
        // draw the border
        //g2d.setColor(Color.gray);
        if (showBorder) {
            Rectangle2D.Double border = new Rectangle2D.Double(2, 2, getPanelWidth(), getPanelHeight());
            g2d.draw(border);
        }

        for (Iterator edges = graph.edgesIterator(); edges.hasNext();) {
            Edge e = (Edge) edges.next();
            int col = e.getType();
            if (showEdges[col - 1]) {
                paintEdge(g2d, e);
            }
        }


        //make sure confidence is restored
        g2d.setComposite(makeComposite(1.0f));
        for (Iterator it = graph.nodesIterator(); it.hasNext();) {
            Node node = (Node) it.next();
            paintNode(g2d, node);
        }
    //PaintTools.paintPath(g2d,10);
    }

    public void saveImage(String path, int param) {
        setShowBorder(false);
        super.saveImage(path, param);
        setShowBorder(true);
    }

    /**
     * Paints the component
     * @param g current graphics
     */
    public synchronized void paintComponent(Graphics g) {

        Graphics2D g2d = prePaint(g);

        // if we have an image, paint it
        drawBackgroundImage(g2d);

        if (hideWhenMove) {
            if ((!running) & (pick != null)) {

                paintVisibleNet(g2d);
            } else {
                paintNet(g2d);
            }
        } else {
            paintNet(g2d);
        }

        //paintNet(g2d);
        //markNode(g2d, marked);
        // for selection boxes
        drawBox(g2d);
        if (drawTempLine) {
            float[] dashPattern = {2, 3, 2, 3};
            g2d.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
                    BasicStroke.JOIN_MITER, 10,
                    dashPattern, 0));
            g2d.drawLine(startx, starty, endx, endy);
        }
        g2d.setStroke(new BasicStroke(1));

    }

    public void paintVisibleNet(Graphics2D g2d) {

        // draw the border
        //g2d.setColor(Color.gray);
        if (showBorder) {
            Rectangle2D.Double border = new Rectangle2D.Double(2, 2, getPanelWidth(), getPanelHeight());
            g2d.draw(border);
        }

        for (Iterator edges = getVisibleGraph().edgesIterator(); edges.hasNext();) {
            Edge e = (Edge) edges.next();
            int col = e.getType();
            if (showEdges[col - 1]) {
                paintEdge(g2d, e);
            }
        }


        //make sure confidence is restored
        g2d.setComposite(makeComposite(1.0f));
        for (Iterator it = graph.nodesIterator(); it.hasNext();) {
            Node node = (Node) it.next();
            paintNode(g2d, node);
        }
    //PaintTools.paintPath(g2d,10);
    }
    //public void loadingMessage(){
    //	Graphics2d g2d =
    protected void drawBox(Graphics2D g2d) {
        if (getCurrentRect() != null) {
            //Draw a rectangle on top of the image.
            g2d.setXORMode(Color.red); //Color of line varies
            //depending on image colors
            float[] dashPattern = {2, 3, 2, 3};
            g2d.setStroke(new BasicStroke(1, BasicStroke.CAP_BUTT,
                    BasicStroke.JOIN_MITER, 10,
                    dashPattern, 0));
            g2d.drawRect(rectToDraw.x, rectToDraw.y,
                    rectToDraw.width - 1, rectToDraw.height - 1);
        }

    }
    protected boolean showName = true;

    /**
     * Switches between showing node name and annotation
     * @param b true if names are to be shown, false if annotation
     */
    public void setShowName(boolean b) {
        showName = b;
        showAnnotation = (!b);
    }

    /**********************
     * // handle editing events (right mouse button)
     ************************/
    private void handleRightMouseDragged(MouseEvent e) {
        if ((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0) {

            // set line drawing to true, and repaint
            drawTempLine = true;
            endx = e.getX();
            endy = e.getY();
            repaint();
        }

        e.consume();
    }

    public void mouseDragged(MouseEvent e) {
        handleLeftMouseDragged(e);
        handleRightMouseDragged(e);

    }

    public void handleReleaseRightButton(MouseEvent e) {
        if (e.getButton() != MouseEvent.BUTTON3) {
            return;
        }
        removeMouseMotionListener(this);
        //int i=getClosest(e);
        Node node = getClosest(e);
        if (node != null) {
            // prompt for new node
            temp2 = node;
        } else {
            temp2 = new Node("unnamed", e.getX(), e.getY());
        }
        drawTempLine = false;
        endx = e.getX();
        endy = e.getY();
        if (temp1 != temp2) {
            //System.out.println(temp1+" "+temp2);
            addEdge();
            repaint();
            temp1 = null;
            temp2 = null;
        } else {
            //System.out.println(temp1.getLabel());
            showPopup(e);
        }

    //System.out.println(temp1+"\n ---> "+temp2);

    }

    public void mouseReleased(MouseEvent e) {
        handleReleaseLeftButton(e);
        handleReleaseRightButton(e);
    }

    private void handlePressRightButton(MouseEvent e) {
        if (e.getButton() == MouseEvent.BUTTON3) {

            addMouseMotionListener(this);
            Node node = getClosest(e);
            //int index=getClosest(e);
            if (node != null) {
                temp1 = node;
                //System.out.println("dragging from "+nodeArray[index]);
                startx = (int) temp1.getX();
                starty = (int) temp1.getY();
            } else {
                startx = e.getX();
                starty = e.getY();
                temp1 = new Node("unnamed", startx, starty);
            }

            e.consume();
        }
    }

    public void mousePressed(MouseEvent e) {

        handlePressLeftButton(e);
        handlePressRightButton(e);
    }    // the edge dialog
    Frame f = new Frame();

    protected void addEdge() {
        //Frame f = new Frame();
        //System.out.println(temp1+" "+temp2);
        Edge e = EdgeDialog.showDialog(f, null, temp1, temp2, getStringSettings());
        if (e != null) {
            temp1.setLabel(e.getFromName());

            temp2.setLabel(e.getToName());

            graph.addEdge(e);
            graph.setNode(temp1);
            graph.setNode(temp2);
            updateNodes();
        }
    }    // to add edges, we need startx, starty, endx and endy. When complete,
    // open the dialog to specify the params
    int startx;
    int starty;
    int endx;
    int endy;
    boolean drawTempLine = false;
    Node temp1 = null;
    Node temp2 = null;    // an array to remember which edges to show/hide
    boolean[] showEdges;

    public void initShow() {
        final int max = 40;
        showEdges = new boolean[max];
        for (int i = 0; i < max; i++) {
            showEdges[i] = true;
        }
    }

    /**
     * Shows the interaction type i
     * @param i interaction type to show
     * @param b true: paint interaction type. false: hide interaction type
     */
    public void setShowEdge(int i, boolean b) {
        showEdges[i] = b;
    }

    public void setHideEdge(int i, boolean b) {
        showEdges[i] = (!b);
    }
    int border = 10;

    /**
     * Sets the shape for fixed nodes
     * @param shape 0-3: implemented shapes in PaintTools
     */
    public void setShape(int shape) {
        for (Iterator it = graph.nodesIterator(); it.hasNext();) {
            Node node = (Node) it.next();
            if (node.isFixed()) {
                node.setShape(shape);
            }
        }
    }
    /* popup!!!!!
     *
     */
    javax.swing.JPopupMenu popup;
    javax.swing.JMenuItem removeItem;
    javax.swing.JMenuItem editColorItem;
    javax.swing.JMenuItem editShapeItem;
    javax.swing.JMenuItem setAnnotationItem;
    javax.swing.JMenuItem getPositionItem;
    javax.swing.JMenu URLItem;
    javax.swing.JMenuItem setURLItem;
    javax.swing.JMenuItem setClusterItem;
    javax.swing.JMenuItem gotoURLItem;
    // show a popup in certain cases
    private void initPopup() {
        //System.out.println("initializing popup");
        popup = new javax.swing.JPopupMenu("Edit data");
        removeItem = new javax.swing.JMenuItem("Delete");
        editColorItem = new javax.swing.JMenuItem("Color");
        editShapeItem = new javax.swing.JMenuItem("Shape");
        setAnnotationItem = new javax.swing.JMenuItem("Annotation");
        URLItem = new javax.swing.JMenu("URL");
        gotoURLItem = new javax.swing.JMenuItem("Go to page");
        setURLItem = new javax.swing.JMenuItem("Edit URL");
        setClusterItem = new javax.swing.JMenuItem("Edit Predefined Cluster");
        getPositionItem = new javax.swing.JMenuItem("Position");
        removeItem.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                if (temp1 != null) {
                    //System.out.println("removing node "+temp1.getLabel());
                    removeEdgeByLabel(temp1.getLabel());
                    temp1 = null;
                    temp2 = null;
                    repaint();
                } else {
                    System.out.println("node is null, for some strange reason");
                }
            }
        });
        editColorItem.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                Color newColor = javax.swing.JColorChooser.showDialog(getRootPane(),
                        "Choose node color",
                        temp1.getColor());
                if (newColor != null) {
                    temp1.setColor(newColor);


                }
                repaint();
            }
        });

        editShapeItem.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {

                temp1.setShape(chooseShape());
                repaint();
            }
        });
        setAnnotationItem.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                setAnnotation(temp1);
            }
        });

        setURLItem.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                setURL(temp1);
            }
        });
        setClusterItem.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                setPredefinedCluster(temp1);
            }
        });

        gotoURLItem.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                if (temp1.getURL().startsWith("http://")) {
                    Browser.openURL(temp1.getURL());
                }
            }
        });

        getPositionItem.addActionListener(new java.awt.event.ActionListener() {

            public void actionPerformed(java.awt.event.ActionEvent e) {
                getPosition(temp1);
            }
        });
        popup.add(removeItem);
        popup.addSeparator();
        popup.add(editColorItem);
        popup.add(editShapeItem);
        popup.add(setAnnotationItem);
        popup.add(URLItem);
        URLItem.add(setURLItem);
        popup.add(setClusterItem);
        URLItem.add(gotoURLItem);
        popup.add(getPositionItem);

    }

    private void getPosition(Node temp) {
        javax.swing.JOptionPane.showMessageDialog(MedusaSimplerFrame.stringletPanel,
                "x: " + temp.getX() + " y:" + temp.getY());
    }

    private void setAnnotation(Node temp) {
        String s = (String) javax.swing.JOptionPane.showInputDialog("View or edit node annotation:\n",
                temp.getAnnotation());
        if ((s != null) && (s.length() > 0)) {
            temp.setAnnotation(s);
        }
    }

    private void setURL(Node temp) {
        String s = (String) javax.swing.JOptionPane.showInputDialog("View or edit node URL:\n",
                temp.getURL());
        if ((s != null) && (s.length() > 0)) {
            if (!s.startsWith("http://")) {
                JOptionPane.showMessageDialog(MedusaSimplerFrame.stringletPanel, "URL does not start with http://");
            } else {
                temp.setURL(s);
            }
        }
    }

    private void setPredefinedCluster(Node temp) {
        String s = (String) javax.swing.JOptionPane.showInputDialog("View or edit node predefined cluster:\n",
                temp.getCLuster());
        if ((s != null) && (s.matches("[0-9]+"))) {
            if ((Integer.parseInt(s) >= 1) || (Integer.parseInt(s) == -1)) {
                temp.setCluster(s);
            } else {
                JOptionPane.showMessageDialog(MedusaSimplerFrame.stringletPanel, "Cluster takes a positive value >1 or -1 for no cluster");
            }
        }
    }

    private int chooseShape() {
        Object[] shapes = {"circle", "rectangle", "triangle", "diamond"};
        int s = javax.swing.JOptionPane.showOptionDialog(this,
                "Choose a node shape",
                "Shape",
                javax.swing.JOptionPane.YES_NO_CANCEL_OPTION,
                javax.swing.JOptionPane.QUESTION_MESSAGE,
                null,
                shapes,
                "circle");
        return s;
    }

    private void showPopup(MouseEvent e) {
        popup.show(e.getComponent(), e.getX(), e.getY());
        e.consume();
    }

    /*
     * manipulate data
     *
     */
    public java.util.ArrayList getFixed() {
        return graph.getFixed();
    }

    public void copyNodeSettings(Graph g) {
        graph.copyNodeSettings(g);
    }

    public void removeEdgeByLabel(String label) {
        //System.out.println("removing "+label);
        graph.removeEdgeByLabel(label);
    }

    public void removeFixedNodes() {
        graph.removeFixed();
    }

    public void crop(double confidence) {
        graph.cropEdges(confidence);
        calculateEdgeLength();
    }
    /* A regular expression search, for finding nodes matching a
     * string. The string should be sent from the front-end.
    
     */

    /* Set a method of marking nodes that users search for
     * by displaying for instance an arrow
     */
    public void markNode(java.awt.Graphics2D g2d, Node markedNode) {
        if (markedNode == null) {
            return;
        }
        // start by just drawing an arrow
        // from ref point 0,0
        int refX = (int) (getPanelWidth() / 2);
        int refY = (int) (getPanelHeight() / 2);
        double r45 = Math.PI / 7.0;
        double deltaLength = 15.0;
        double headLength = 13.0;

        // get theta
        double x = markedNode.getX();
        double y = markedNode.getY();
        double deltaX = (x - refX);
        double deltaY = -(y - refY);
        double theta = Math.atan(deltaY / deltaX);
        if (deltaX < 0.0) {
            theta += Math.PI;        // get x,y for the head point
        }
        int xh = (int) (x - deltaLength * Math.cos(theta));
        int yh = (int) (y + deltaLength * Math.sin(theta));

        // get clockwise shoulder point
        int xc = (int) (xh - headLength * Math.cos(theta - r45));
        int yc = (int) (yh + headLength * Math.sin(theta - r45));

        // get anti-clockwise shoulder point
        int xa = (int) (xh - headLength * Math.cos(theta + r45));
        int ya = (int) (yh + headLength * Math.sin(theta + r45));

        // the shadow
        int shad = 3;
        // build a polygon from this
        int[] xpoints = {xc, xh, xa};
        int[] ypoints = {yc, yh, ya};
        int[] shadowX = {xc + shad, xh + shad, xa + shad};
        int[] shadowY = {yc + shad, yh + shad, ya + shad};
        int npoints = 3;

        // draw it
        //g2d.setColor(Color.magenta);
        g2d.setColor(Color.black);
        g2d.fillPolygon(shadowX, shadowY, npoints);
        g2d.setColor(Color.orange);
        g2d.fillPolygon(xpoints, ypoints, npoints);

        g2d.setColor(Color.black);

    }

    public int selectNodeByRegExp(final String regexp, boolean label) {
        int matches = 0;
        Pattern labelPattern = Pattern.compile(regexp);
        Matcher matcher;
        // loop through and fix nodes that match the expression
        for (Iterator it = graph.nodesIterator(); it.hasNext();) {
            Node node = (Node) it.next();
            String toMatch = label ? node.getLabel() : node.getAnnotation();
            matcher = labelPattern.matcher(toMatch);
            if (matcher.find()) {
                node.setFixed(true);
                matches++;
            }
        }
        return matches;
    }

    /**
     * Reads a file of node names and selected those nodes in the graph.
     * @param fileName
     * @throws java.io.IOException
     * @return
     */
    public int selectNodeFromFile(final String fileName) throws IOException {
        int matches = 0;
        String inLine;
        File loadFile = new File(fileName);
        BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(loadFile)));
        while ((inLine = in.readLine()) != null) {
            for (Iterator it = graph.nodesIterator(); it.hasNext();) {
                Node node = (Node) it.next();
                if (node.getLabel().compareTo(inLine) == 0) {
                    matches++;
                    node.setFixed(true);
                    continue;
                }
            }
        }
        in.close();
        return matches;
    }

    public void manipulateColor(int a, int b, boolean doSwitch) {
        for (Iterator it = graph.nodesIterator(); it.hasNext();) {
            Node node = (Node) it.next();
            if (node.isFixed()) {
                node.manipulateColorElement(a, b, doSwitch);
            }
        }
    }

    public void addGradientX(int channel) {
        int value;
        for (Iterator it = graph.nodesIterator(); it.hasNext();) {
            Node node = (Node) it.next();
            if (node.isFixed()) {
                value = (int) (node.getX() / getPanelWidth() * 255.0);
                //System.out.println(node.getLabel()+" "+value);
                node.manipulateChannel(channel, value);
            }
        }
    }

    public void addGradientY(int channel) {
        int value;
        for (Iterator it = graph.nodesIterator(); it.hasNext();) {
            Node node = (Node) it.next();
            if (node.isFixed()) {
                value = (int) (node.getY() / getPanelWidth() * 255.0);
                //System.out.println(node.getLabel()+" "+value);
                node.manipulateChannel(channel, value);
            }
        }
    }

    public void clearGraph() {
        graph.clear();
        updateNodes();
    }    //Timer loadTimer;
    //public void loadGraphThread(){
    //	loadTimer = new Timer(200,loadGraphThreadActionEvent);
    DataLoader dl = new DataLoader(getPanelWidth(), getPanelHeight());

    public void loadGraph(String fileName) throws IOException, DataFormatException {
        graph = dl.load(fileName);
        updateNodes();
    }

    public void saveGraph(String fileName) throws IOException {
        dl.save(graph, fileName, scale);
        updateNodes();
    }

    public void writePajek(String fileName) throws IOException {
        dl.saveAsPajek(graph, fileName);
    }

    public void writeArena3D(String fileName) throws IOException {
        dl.saveAsArena3D(graph, fileName);
    }

    public void writeCytoscape(String fileName) throws IOException {
        dl.saveAsCytoscape(graph, fileName);
    }

    public void writeGraphViz(String fileName) throws IOException {
        dl.saveAsGraphViz(graph, fileName);
    }

    public void writeBiolayout(String fileName) throws IOException {
        dl.saveAsBiolayout(graph, fileName);
    }

    public void writePS(String fileName) throws IOException {
        dl.saveAsPS(graph, fileName, getStringSettings(), nodeSize, fontSize);
    //updateNodes();
    }

    public void writeEPS(String fileName) throws IOException {
        dl.saveAsEPS(graph, fileName, getStringSettings(), nodeSize, fontSize);
    //updateNodes();
    }
    /* Data manipulation tools
     */

    public void appendGraph(String fileName) throws IOException, DataFormatException {
        Graph temp = dl.load(fileName);
        graph.addGraph(temp);
        copyNodeSettings(temp);
        calculateEdgeLength();
        //System.out.println(graph.report());
        updateNodes();
    }

    public void subtractGraph(String fileName) throws IOException, DataFormatException {
        Graph temp = dl.load(fileName);
        graph.subtractGraph(temp);
        copyNodeSettings(temp);
        calculateEdgeLength();
        //System.out.println(graph.report());
        updateNodes();
    }

    public void copyGraphSettings(String fileName) throws IOException, DataFormatException {
        Graph temp = dl.load(fileName);
        //graph.addGraph(temp);
        copyNodeSettings(temp);
        //calculateEdgeLength();
        //System.out.println(graph.report());
        updateNodes();
    }

    public void addGraph(Graph g) {
        if (g == null) {
            return;
        }
        g.rescaleNodes(600);
        graph.addGraph(g);
        copyNodeSettings(g);
    }

    public void growSelection() {
        // get a temp graph of fixed nodes
        graph.growSelection();
    }
//    
//    public void shrinkGraph(){
//        graph.shrinkGraph()
//    }
    public void alignNodes(int align) {
        List nodes = getFixed();
        // find the left-most node
        int y = 0;
        Node node = getExtremeNode(align, nodes);
        if (node==null){
            //System.out.println("null! (EditableGraphPanel)");
            return;
        }
        //System.out.println("not null! (EditableGraphPanel) "+node.getLabel());
        for (int i = 0; i < nodes.size(); i++) {
            Node n = nodes.get(i);
            if ((align == EXTREME_LEFT) || (align == EXTREME_RIGHT)) {
                n.setY(node.getY());

            }
            if ((align == EXTREME_TOP) || (align == EXTREME_BOTTOM)) {
                n.setX(node.getX());

            }
        }
    }
    
    
    
    public static int EXTREME_LEFT = 9001;
    public static int EXTREME_RIGHT = 9002;
    public static int EXTREME_TOP = 9003;
    public static int EXTREME_BOTTOM = 9004;

    public Node getExtremeNode(int extreme, List nodes) {
        double leftValue = Double.MAX_VALUE;
        double topValue = Double.MAX_VALUE;
        double rightValue = 0.0;
        double bottomValue = 0.0;
        int left = 0;
        int right = 0;
        int top = 0;
        int bottom = 0;
        for (int i = 0; i < nodes.size(); i++) {
            Node n = nodes.get(i);
            if (n.getX() < leftValue) {
                leftValue = n.getX();
                left = i;
            }
            if (n.getX() > rightValue) {
                rightValue = n.getX();
                right = i;
            }
            if (n.getY() < topValue) {
                topValue = n.getY();
                top = i;
            }
            if (n.getY() > bottomValue) {
                bottomValue = n.getY();
                bottom = i;
            }
        }
        if (extreme == EXTREME_LEFT) {
            return nodes.get(left);

        }
        if (extreme == EXTREME_RIGHT) {
            return nodes.get(right);

        }
        if (extreme == EXTREME_TOP) {
            return nodes.get(top);

        }
        if (extreme == EXTREME_BOTTOM) {
            return nodes.get(bottom);

        }
        return null;
    }
}



 

Ads help maintain this website.