001    /* EVolve - an Extensible Software Visualization Framework
002     * Copyright (C) 2001-2002 Qin Wang
003     *
004     * This library is free software; you can redistribute it and/or
005     * modify it under the terms of the GNU Library General Public
006     * License as published by the Free Software Foundation; either
007     * version 2 of the License, or (at your option) any later version.
008     *
009     * This library is distributed in the hope that it will be useful,
010     * but WITHOUT ANY WARRANTY; without even the implied warranty of
011     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
012     * Library General Public License for more details.
013     *
014     * You should have received a copy of the GNU Library General Public
015     * License along with this library; if not, write to the
016     * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017     * Boston, MA 02111-1307, USA.
018     */
019    
020    /*
021     * EVolve is distributed at http://www.sable.mcgill.ca/EVolve/
022     */
023    
024    package EVolve.visualization;
025    
026    import java.awt.*;
027    import java.awt.event.*;
028    import java.awt.geom.*;
029    import java.awt.image.*;
030    import javax.swing.*;
031    
032    /**
033     * Panel with two axes.
034     */
035    public class AxesPanel extends JPanel {
036        private String xName, yName; // names of the axes
037        private BufferedImage image; // content
038    
039        private double startX, startY, endX, endY; // relative position of the selection box
040        private boolean drawBox; // whether is drawing the box or not
041    
042        private boolean drawPointer;
043        private boolean drawAxis;
044        private int xPos, yPos;
045        private int scaleX, scaleY;
046        private int originX,originY;
047    
048        /**
049         * Creates an axes panel.
050         */
051        public AxesPanel() {
052            xName = "X-axis";
053            yName = "Y-axis";
054            image = null;
055    
056            startX = 0.0;
057            startY = 0.0;
058            endX = 0.0;
059            endY = 0.0;
060            drawBox = false;
061    
062            drawPointer = false;
063            drawAxis = true;
064            xPos = 0;
065            yPos = 0;
066            scaleX = 60;
067            scaleY = 60;
068            originX = 20;
069            originY = 20;
070    
071            addMouseListener(new MouseAdapter() {
072                public void mousePressed(MouseEvent e) {
073                    if (e.getButton() == MouseEvent.BUTTON1) {
074                        mPressed(e.getX(), e.getY());
075                    }
076                }
077            });
078    
079            addMouseListener(new MouseAdapter() {
080                public void mouseReleased(MouseEvent e) {
081                    if (e.getButton() == MouseEvent.BUTTON1) {
082                        mReleased();
083                    }
084                }
085            });
086    
087            addMouseMotionListener(new MouseMotionAdapter() {
088                public void mouseDragged(MouseEvent e) {
089                    if (drawBox) {
090                        mDragged(e.getX(), e.getY());
091                    }
092                }
093            });
094        }
095    
096        public AxesPanel(boolean showAxis) {
097            this();
098            drawAxis = showAxis;
099            scaleX = 0;
100            scaleY = 0;
101            originX = 0;
102            originY = 0;
103        }
104    
105        /**
106         * Mouse pressed.
107         *
108         * @param   x position on X-axis
109         * @param   y position on Y-axis
110         */
111        private void mPressed(int x, int y) {
112            if (image != null) {
113                int w = getWidth();
114                int h = getHeight();
115                startX = ((double)(x - 20)) / ((double)(w - 60));
116                startY = ((double)(y - 40)) / ((double)(h - 60));
117                endX = ((double)(x - 20)) / ((double)(w - 60));
118                endY = ((double)(y - 40)) / ((double)(h - 60));
119                drawBox = true;
120                repaint();
121            }
122        }
123    
124        /**
125         * Mouse released.
126         */
127        private void mReleased() {
128            if (image != null) {
129                drawBox = false;
130            }
131        }
132    
133        /**
134         * Mouse dragged.
135         *
136         * @param   x position on X-axis
137         * @param   y position on Y-axis
138         */
139        private void mDragged(int x, int y) {
140            if (image != null) {
141                int w = getWidth();
142                int h = getHeight();
143                endX = ((double)(x - 20)) / ((double)(w - 60));
144                endY = ((double)(y - 40)) / ((double)(h - 60));
145                repaint();
146            }
147        }
148    
149        /**
150         * Sets the names of the axes.
151         *
152         * @param   xName name of the X-axis
153         * @param   yName name of the Y-axis
154         */
155        public void setName(String xName, String yName) {
156            this.xName = xName;
157            this.yName = yName;
158        }
159    
160        /**
161         * Sets the content of the panel.
162         *
163         * @param   image content
164         */
165        public void setImage(BufferedImage image) {
166            this.image = image;
167    
168            startX = 0.0;
169            startY = 0.0;
170            endX = 0.0;
171            endY = 0.0;
172            drawBox = false;
173        }
174    
175        /**
176         * Draws the panel.
177         *
178         * @param   g graphics
179         */
180        public void paintComponent(Graphics g) {
181            super.paintComponent(g);
182    
183            Graphics2D g2 = (Graphics2D)g;
184    
185            int w = getWidth();
186            int h = getHeight();
187    
188            if (drawAxis) {
189                g2.setColor(Color.white);
190                g2.fillRect(0, 0, w, h);
191    
192                g2.setColor(Color.black);
193                g2.drawLine(20, h - 20, w - 20, h - 20);
194                g2.drawLine(w - 20, h - 20, w - 30, h - 15);
195                g2.drawLine(w - 20, h - 20, w - 30, h - 25);
196                g2.drawLine(20, h - 20, 20, 20);
197                g2.drawLine(20, 20, 15, 30);
198                g2.drawLine(20, 20, 25, 30);
199    
200    
201                Font font = new Font("Arial", Font.PLAIN, 12);
202                g2.setFont(font);
203                g2.drawString(xName, w - g2.getFontMetrics().stringWidth(xName) - 40, h - 5);
204                g2.rotate(-Math.PI / 2.0);
205                g2.drawString(yName, -40 - g2.getFontMetrics().stringWidth(yName), 15);
206                g2.rotate(Math.PI / 2.0);
207            }
208            if (image != null) {
209                AffineTransform tf = g2.getTransform();
210                g2.translate(originX+1, (h - originY));
211                g2.scale((double)(w - scaleX) / (double)(image.getWidth()), -(double)(h - scaleY) / (double)(image.getHeight()));
212                g2.drawImage(image, 0, 0, null);
213                g2.setTransform(tf);
214    
215                g2.setColor(Color.blue);
216                double x1 = (startX < endX) ? startX : endX;
217                double x2 = (startX > endX) ? startX : endX;
218                double y1 = (startY < endY) ? startY : endY;
219                double y2 = (startY > endY) ? startY : endY;
220                g2.drawRect((int)(x1 * ((double)(w - scaleX))) + 20, (int)(y1 * ((double)(h - scaleY))) + 40, (int)((x2 - x1) * ((double)(w - scaleX))), (int)((y2 - y1) * ((double)(h - scaleY))));
221            }
222            if (drawPointer) {
223                g2.setColor(Color.black);
224                g2.drawLine(xPos,yPos,xPos+20,yPos+20);
225                g2.drawLine(xPos,yPos,xPos+10,yPos+5);
226                g2.drawLine(xPos,yPos,xPos+5,yPos+10);
227            }
228    
229        }
230    
231        /**
232         * Gets the X-axis value of the image.
233         *
234         * @param   x X-axis value of the panel
235         * @return  X-axis value of the image
236         */
237        public int getImageX(int x) {
238            int w = getWidth();
239            if ((image == null)||(w-scaleX==0)) {
240                return -1;
241            } else {
242                return (x - originX) * image.getWidth() / (w - scaleX);
243            }
244        }
245    
246        public double getScreenXDelta(double delta) {
247            int w = getWidth();
248            return (delta*w/image.getWidth());
249        }
250    
251        /**
252         * Gets the Y-axis value of the image.
253         *
254         * @param   y Y-axis value of the panel
255         * @return  Y-axis value of the image
256         */
257        public int getImageY(int y) {
258            int h = getHeight();
259            if ((image == null)||(h-scaleY==0)) {
260                return -1;
261            } else {
262                return (h - originY - y) * image.getHeight() / (h - scaleY);
263            }
264        }
265    
266        public double getScreenYDelta(double delta) {
267            int h = getHeight();
268            return (delta*(h-delta)/image.getHeight());
269        }
270    
271        public int getScreenY(int y) {
272            int guessedY;
273            int h = getHeight();
274    
275            guessedY = h-20-y*(h-60)/image.getHeight();
276            for (int j = guessedY-20; j< guessedY+20; j++) {
277                if (getImageY(j) == y) {
278                    guessedY = j;
279                    break;
280                }
281            }
282            return guessedY;
283        }
284    
285        /**
286         * Gets the start position of the selection box on X-axis.
287         *
288         * @return  start position of the selection box on X-axis
289         */
290        public int getStartX() {
291            int w = getWidth();
292            double x = (startX < endX) ? startX : endX;
293            return getImageX((int)(x * ((double)(w - 60))) + 20);
294        }
295    
296        /**
297         * Gets the end position of the selection box on X-axis.
298         *
299         * @return  end position of the selection box on X-axis
300         */
301        public int getEndX() {
302            int w = getWidth();
303            double x = (startX > endX) ? startX : endX;
304            return getImageX((int)(x * ((double)(w - 60))) + 20);
305        }
306    
307        /**
308         * Gets the start position of the selection box on Y-axis.
309         *
310         * @return  start position of the selection box on Y-axis
311         */
312        public int getStartY() {
313            int h = getHeight();
314            double y = (startY < endY) ? startY : endY;
315            return getImageY((int)(y * ((double)(h - 60))) + 40);
316        }
317    
318        /**
319         * Gets the end position of the selection box on Y-axis.
320         *
321         * @return  end position of the selection box on Y-axis
322         */
323        public int getEndY() {
324            int h = getHeight();
325            double y = (startY > endY) ? startY : endY;
326            return getImageY((int)(y * ((double)(h - 60))) + 40);
327        }
328    
329        public void drawPointer(boolean draw) {
330            drawPointer = draw;
331        }
332    
333        public void setPointerPosition(int xPos, int yPos) {
334            this.xPos = xPos;
335            this.yPos = yPos;
336        }
337    
338        public void drawZoomingArea(int x, int y) {
339            double deltaX = getScreenXDelta(10);
340            double deltaY = getScreenYDelta(10);
341            int w = getWidth(), h = getHeight();
342    
343            startX = (x - deltaX-20)/(double)(w-scaleX);
344            startY = (y -deltaY-40)/(double)(h-scaleY);
345            endX = (x + deltaX-20)/(double)(w-scaleX);
346            endY = (y + deltaY-40)/(double)(h-scaleY);
347    
348            drawBox = true;
349            repaint();
350            drawBox = false;
351        }
352    }
353    
354    
355    /*
356        public void setParent(Visualization visual) {
357            parent = visual;
358        }
359    
360        public void drawCallLines(ArrayList coord) {
361            Graphics2D g2 = (Graphics2D)this.getGraphics();
362            int x1,y1,x2,y2;
363    
364            if (coord == null) {// clear the viz
365                coords = null;
366                repaint();
367                return;
368            }
369    
370    
371            for (int j=0; j<coord.size()/2 -1; j++) {
372                x1 = ((Integer)coord.get(j*2)).intValue();
373                y1 = ((Integer)coord.get(j*2+1)).intValue();
374                x2 = ((Integer)coord.get(j*2+2)).intValue();
375                y2 = ((Integer)coord.get(j*2+3)).intValue();
376                g2.drawLine(x1,y1,x2,y2);
377                double len = java.lang.Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
378                double angle = java.lang.Math.asin(java.lang.Math.abs(y1-y2)/len);
379    
380                if (x1>x2) {
381                    if (y1 < y2)
382                        angle = 2*java.lang.Math.PI - angle;
383                } else {
384                    if (y1 > y2)
385                        angle = java.lang.Math.PI - angle;
386                    else
387                        angle = java.lang.Math.PI + angle;
388                }
389                g2.drawLine(x2,y2,(int)(x2+15*java.lang.Math.cos(angle-0.5236)),(int)(y2+15*java.lang.Math.sin(angle-0.5236)));
390                g2.drawLine(x2,y2,(int)(x2+15*java.lang.Math.cos(angle+0.5236)),(int)(y2+15*java.lang.Math.sin(angle+0.5236)));
391    
392                //System.out.println("draw from "+x1+","+y1+" to "+x2+","+y2 );
393           }
394    
395            if (coords == null) coords = new ArrayList();
396            coords.add(coord);
397        } */
398    
399    /*
400                /*if (parent != null) {
401                    ReferenceDimension xAxis = (ReferenceDimension) parent.getDimension()[0];
402                    int X = this.getImageX(x);
403                    int Y = this.getImageY(y);
404                    if ((Y >= 0) && (Y < xAxis.getEntityNumber()) && (X >= 0) && (X < xAxis.getEntityNumber())) {
405                        Color color = parent.getImage().getSortedColor(xAxis,xAxis,X,Y);
406                        //if (color==null) coords = null;
407                   }
408                }
409    
410        if (coords == null) return;
411            int x1,x2,y1,y2;
412            x1=x2=y1=y2=0;
413    
414            g2.setColor(Color.black);
415            for (int i=0; i< coords.size(); i++) {
416                ArrayList coord = (ArrayList)coords.get(i);
417                for (int j=0; j<coord.size()/2 -1; j++) {
418                    x1 = ((Integer)coord.get(j*2)).intValue();
419                    y1 = ((Integer)coord.get(j*2+1)).intValue();
420                    x2 = ((Integer)coord.get(j*2+2)).intValue();
421                    y2 = ((Integer)coord.get(j*2+3)).intValue();
422                    g2.drawLine(x1,y1,x2,y2);
423                    double len = java.lang.Math.sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
424                    double angle = java.lang.Math.asin(java.lang.Math.abs(y1-y2)/len);
425                    if (len == 0) continue;
426                    if (x1>x2) {
427                        if (y1 < y2)
428                            angle = 2*java.lang.Math.PI - angle;
429                    } else {
430                        if (y1 > y2)
431                            angle = java.lang.Math.PI - angle;
432                        else
433                            angle = java.lang.Math.PI + angle;
434                    }
435                    g2.drawLine(x2,y2,(int)(x2+10*java.lang.Math.cos(angle-0.5236)),(int)(y2+10*java.lang.Math.sin(angle-0.5236)));
436                    g2.drawLine(x2,y2,(int)(x2+10*java.lang.Math.cos(angle+0.5236)),(int)(y2+10*java.lang.Math.sin(angle+0.5236)));
437                }
438            }*/