001    /**
002     * Created by IntelliJ IDEA.
003     * User: Wei Wang
004     * Date: Mar 2, 2003
005     * Time: 9:05:11 PM
006     */
007    
008    package EVolve.visualization;
009    
010    import java.awt.Color;
011    import java.awt.Font;
012    import java.awt.Graphics;
013    import java.awt.Graphics2D;
014    import java.awt.Point;
015    import java.awt.event.MouseAdapter;
016    import java.awt.event.MouseEvent;
017    import java.awt.event.MouseMotionAdapter;
018    import java.awt.geom.AffineTransform;
019    import java.awt.geom.Point2D;
020    import java.awt.geom.Rectangle2D;
021    import java.awt.image.BufferedImage;
022    import java.util.ArrayList;
023    
024    import javax.swing.JPanel;
025    import javax.swing.JScrollPane;
026    
027    import EVolve.exceptions.NoDataPlotException;
028    
029    public class AxesPanel extends JPanel{
030        public final static int Axis_Enabled = 0x00001;
031        public final static int Scale_Image = 0x11000000;
032        public final static int Flip_Image = 0x00100;
033        public final static int Pointer_Enabled = 0x01000;
034        public final static int Box_Enabled = 0x10000;
035        public final static int Null = 0x0;
036        public final static int Scale_X = 0x10000000;
037        public final static int Scale_Y = 0x01000000;
038    
039        private int flag;
040        private String xName=" ", yName=" ";
041        private Point origin, imageAdjustment, pointerPosition;
042        private Point boxStart, boxEnd;
043        private Point2D.Double mousePos;
044        private int zoomingWidth, zoomingHeight, shapeSize;
045        private BufferedImage image;
046        private JScrollPane parent = null;
047        private ArrayList phases, stringList;
048    
049        private AutoImage autoImage;
050        private double factorX, factorY;
051    
052        public AxesPanel(int flag) {
053            this.flag = flag;
054            origin = new Point(0,0);
055            imageAdjustment = new Point(0,0);
056            pointerPosition = new Point(0,0);
057            boxStart = new Point(0,0);
058            boxEnd = new Point(0,0);
059            mousePos = new Point2D.Double(0,0);
060            zoomingWidth = zoomingHeight = 20;
061            shapeSize = 1;
062            stringList = new ArrayList();
063            factorX = factorY = 1;
064            if ((flag & 0x000f) == Axis_Enabled) {
065                origin.setLocation(20,20);
066                imageAdjustment.x = 60;
067                imageAdjustment.y = 60;
068            }
069            addMouseListener(new MouseAdapter() {
070                public void mousePressed(MouseEvent e) {
071                    if (e.getButton() == MouseEvent.BUTTON1) {
072                        mPressed(e.getX(), e.getY());
073                    }
074                }
075            });
076    
077            addMouseListener(new MouseAdapter() {
078                public void mouseReleased(MouseEvent e) {
079                    if (e.getButton() == MouseEvent.BUTTON1) {
080                        mReleased();
081                    }
082                }
083            });
084    
085            addMouseMotionListener(new MouseMotionAdapter() {
086                public void mouseDragged(MouseEvent e) {
087                    mDragged(e.getX(), e.getY());
088                }
089            });
090        }
091    
092        private void drawAxis(Graphics2D g2) {
093    
094            if ((flag & 0x000f)==Axis_Enabled) {//axis is enabled
095                int w = getWidth(), h = getHeight();
096                g2.setColor(Color.black);
097                g2.drawLine(origin.x, h - origin.y, w - origin.x, h - origin.x);
098                g2.drawLine(w - origin.x, h - origin.y, w - 30, h - 15);
099                g2.drawLine(w - origin.x, h - origin.y, w - 30, h - 25);
100                g2.drawLine(origin.x, h - origin.y, origin.x, origin.y);
101                g2.drawLine(origin.x, origin.y, 15, 30);
102                g2.drawLine(origin.x, origin.y, 25, 30);
103    
104    
105                Font font = new Font("Arial", Font.PLAIN, 12);
106                g2.setFont(font);
107                g2.drawString(xName, w - g2.getFontMetrics().stringWidth(xName) - 40, h - 5);
108                g2.rotate(-Math.PI / 2.0);
109                g2.drawString(yName, -40 - g2.getFontMetrics().stringWidth(yName), 15);
110                g2.rotate(Math.PI / 2.0);
111            }
112        }
113    
114        private void drawImage(Graphics2D g2) {
115            int h = getHeight(), flip = 1;
116            AffineTransform tf = g2.getTransform();
117    
118            if ((flag&0x0f00)==Flip_Image) {
119                flip = -1;
120                g2.translate(origin.x+1, h - origin.y);
121            }
122    
123            calcScaleFactors();
124    
125            g2.scale(factorX,(double)flip*factorY);
126            g2.drawImage(image, 0, 0, null);
127            g2.setTransform(tf);
128        }
129    
130        private void drawBox(Graphics2D g2) {
131            g2.setColor(Color.blue);
132            int x1 = (boxStart.x < boxEnd.x) ? boxStart.x : boxEnd.x;
133            int x2 = (boxStart.x > boxEnd.x) ? boxStart.x : boxEnd.x;
134            int y1 = (boxStart.y < boxEnd.y) ? boxStart.y : boxEnd.y;
135            int y2 = (boxStart.y > boxEnd.y) ? boxStart.y : boxEnd.y;
136            g2.drawRect(x1, y1, x2 - x1, y2 - y1);
137        }
138    
139        private void drawPhases(Graphics2D g2) {
140            int w = getWidth(), h = getHeight();
141    
142            if ((phases == null)||(phases.size() == 0)) return;
143    
144            calcScaleFactors();
145    
146            g2.setColor(Color.black);
147    
148            int lastX = 0, currentX = 0;
149            for (int i=0; i<phases.size(); i++) {
150                int phaseEnd = ((Integer)phases.get(i)).intValue();
151    
152                if (phaseEnd <= 0) continue;
153    
154                currentX = (int)(phaseEnd*factorX)+origin.x;
155                g2.drawString(String.valueOf(phaseEnd),currentX,10+(i%2)*10);
156                g2.drawString("("+i+")", (currentX + lastX)/2-5, 30);
157                g2.drawLine(currentX, h-origin.y, (int)(phaseEnd*factorX)+origin.x, origin.y);
158                lastX = currentX;
159            }
160            g2.drawString("("+phases.size()+")", (currentX + w)/2-5, 30);
161    
162        }
163    
164        private void drawPointer(Graphics2D g2) {
165            if ((flag&0xf000)==Pointer_Enabled) {
166                int x = pointerPosition.x, y = pointerPosition.y;
167                g2.setColor(Color.black);
168                g2.drawLine(x,y,x+20,y+20);
169                g2.drawLine(x,y,x+10,y+5);
170                g2.drawLine(x,y,x+5,y+10);
171            }
172        }
173    
174        private void setPreferredPanelSize() {
175            if (parent == null) return;
176            int width = image.getWidth()+imageAdjustment.x;
177            int height = image.getHeight()+imageAdjustment.y;
178    
179            if ((flag&0xf0000000) == Scale_X)
180                width = parent.getWidth() - 14;
181            if ((flag&0x0f000000) == Scale_Y)
182                height = parent.getHeight()-14;
183    
184            setPreferredSize(new java.awt.Dimension(width, height));
185            /*if ((flag&0xff000000) != Scale_Image) {
186                setPreferredSize(new java.awt.Dimension(image.getWidth()+imageAdjustment.x,image.getHeight()+imageAdjustment.y));
187            } else {
188                setPreferredSize(new java.awt.Dimension(parent.getWidth()-14, parent.getHeight()-14));
189            }*/
190            revalidate();
191        }
192    
193        private void drawStrings(Graphics2D g2) {
194            for (int i=0; i<stringList.size(); i++) {
195                Object[] values = (Object[])stringList.get(i);
196                int x = ((Integer)values[0]).intValue() - origin.x;
197                int y = ((Integer)values[1]).intValue();
198                String content = (String)values[2];
199    
200                if ((flag & 0xf0000000) == Scale_X)
201                    x = (int) ((float)x*(float)(getWidth()-imageAdjustment.x)/(float)image.getWidth()+origin.x);
202                else
203                    x = x + origin.x;
204    
205                if ((flag & 0x0f000000) == Scale_Y) {
206                    if ((flag & 0x00f00) == Flip_Image)
207                        y = (int)((float)getHeight()-(float)origin.y-(float)y*(float)(getHeight()-imageAdjustment.y)/(float)image.getHeight());
208                    else
209                        y = (int)((float)y*(float)(getHeight()-imageAdjustment.y)/(float)image.getHeight()+(float)origin.y);
210                }
211                else {
212                    if ((flag & 0x00f00) == Flip_Image)
213                        y = getHeight()-origin.y-y;
214                    else
215                        y = y + origin.y;
216                }
217                g2.drawString(content,x,y);
218            }
219        }
220    
221        public void paintComponent(Graphics g) {
222            super.paintComponent(g);
223    
224            Graphics2D g2 = (Graphics2D)g;
225    
226            int w = getWidth();
227            int h = getHeight();
228    
229            g2.setColor(Color.white);
230            g2.fillRect(0, 0, w, h);
231    
232            drawAxis(g2);
233    
234            if (image != null) {
235                setPreferredPanelSize();
236                drawImage(g2);
237                drawPhases(g2);
238                drawBox(g2);
239                drawStrings(g2);
240            }
241            drawPointer(g2);
242    
243        }
244    
245        protected void mPressed(int x, int y) {
246            if (image != null) {
247                boxStart.x = x;
248                boxStart.y = y;
249                boxEnd.x = x;
250                boxEnd.y = y;
251                flag = flag | Box_Enabled;
252                repaint();
253            }
254        }
255    
256        protected void mReleased() {
257            if (image != null) {
258                flag = flag & 0xff00ffff;
259            }
260        }
261    
262        protected void mDragged(int x, int y) {
263            if ((image != null)&&((flag &0xf0000) == Box_Enabled)) {
264                boxEnd.x = x;
265                boxEnd.y = y;
266                repaint();
267            }
268        }
269    
270        public void setName(String xName, String yName) {
271            this.xName = xName;
272            this.yName = yName;
273        }
274    
275        public void setImage(BufferedImage image) {
276            this.image = image;
277    
278            boxStart.x = 0;
279            boxStart.y = 0;
280            boxEnd.x = 0;
281            boxEnd.y = 0;
282            flag = flag & 0xff00ffff;
283        }
284    
285        public void setAutoImage(AutoImage autoImage) throws NoDataPlotException{
286            this.autoImage = null;
287            this.autoImage = autoImage;
288            this.autoImage.setPhases(phases);
289            image = autoImage.getImage();
290        }
291    
292        public int getImageX(int x) {
293            if (image == null) return -1;
294    
295            if ((flag & 0xf0000000) == Scale_X)
296                return (int)((float)(x-origin.x)*((float)image.getWidth()/(float)(getWidth()-imageAdjustment.x)));
297            else
298                return x - origin.x;
299        }
300    
301        public int getImageY(int y) {
302            if (image == null) return -1;
303    
304            if ((flag & 0x0f000000) == Scale_Y) {
305                if ((flag & 0x00f00) == Flip_Image)
306                    return (int)((float)(getHeight()-origin.y-y)*((float)image.getHeight()/(float)(getHeight()-imageAdjustment.y)));
307                else
308                    return (int)((float)(y-origin.y)*((float)image.getHeight()/(float)(getHeight()-imageAdjustment.y)));
309            }
310            else {
311                if ((flag & 0x00f00) == Flip_Image)
312                    return getHeight()-origin.y-y;
313                else
314                    return y - origin.y;
315            }
316        }
317    
318        public int getStartX() {
319            int x = (boxStart.x < boxEnd.x) ? boxStart.x : boxEnd.x;
320            return getImageX(x);
321        }
322    
323        public int getEndX() {
324            int x = (boxStart.x > boxEnd.x) ? boxStart.x : boxEnd.x;
325            return getImageX(x);
326        }
327    
328        public int getStartY() {
329            int y = (boxStart.y < boxEnd.y) ? boxStart.y : boxEnd.y;
330            return getImageY(y);
331        }
332    
333        public int getEndY() {
334            int y = (boxStart.y > boxEnd.y) ? boxStart.y : boxEnd.y;
335            return getImageY(y);
336        }
337    
338        public void setPointerPosition(int x, int y) {
339            pointerPosition.x = x;
340            pointerPosition.y = y;
341        }
342    
343        public void enablePointer(boolean draw) {
344            if (draw)
345                flag = flag | Pointer_Enabled;
346            else
347                flag = flag & (~Pointer_Enabled);
348        }
349    
350        private Rectangle2D.Double calcZoomingArea(int x, int y) {
351            int w = image.getWidth(), h = image.getHeight();
352    
353            double x1=x,y1=y,w1,h1;
354    
355            x1 = x1 - (double)zoomingWidth*shapeSize/2;
356            y1 = y1 - (double)zoomingHeight*shapeSize/2;
357    
358            w1 = zoomingWidth*shapeSize;
359            h1 = zoomingHeight*shapeSize;
360    
361            mousePos.setLocation(shapeSize*zoomingWidth/2,shapeSize*zoomingHeight/2);
362            if (x1 < 0) {
363                mousePos.x+=x1;
364                w1 = w1+x1;
365                x1 = 0;
366            }
367            if (x1 + w1 > w) {
368                w1 = w - x1;
369            }
370    
371            if (y1 < 0) {
372                mousePos.y+=y1;
373                h1 = h1+y1;
374                y1 = 0;
375            }
376            if (y1 + h1 > h) {
377                h1 = h - y1;
378            }
379    
380            Rectangle2D.Double ret = new Rectangle2D.Double();
381            ret.x = x1;
382            ret.y = y1;
383            ret.width = w1;
384            ret.height = h1;
385            return ret;
386        }
387    
388        public BufferedImage getSubImage(int x, int y) {
389            int w = image.getWidth(), h = image.getHeight();
390            Rectangle2D.Double zooming = calcZoomingArea(x,y);
391    
392            if ((image == null)||(zooming.x>w)||(zooming.y>h))
393                return null;
394    
395            if ((zooming.width<=0) || (zooming.height<=0)) return null;
396    
397            return image.getSubimage((int)zooming.x,(int)zooming.y,(int)zooming.width,(int)zooming.height);
398        }
399    
400        public void drawZoomingArea(int x, int y) {
401            double coX = 1, coY = 1;
402    
403            if ((flag & 0xf0000000) == Scale_X) {
404                coX = (double)(getWidth() - imageAdjustment.x)/(double)image.getWidth();
405            }
406            if ((flag & 0x0f0000000) == Scale_Y) {
407                coY = (double)(getHeight() - imageAdjustment.y)/(double)image.getHeight();
408            }
409            int deltaX = (int)(coX*zoomingWidth*shapeSize/2);
410            int deltaY = (int)(coY*zoomingHeight*shapeSize/2);
411    
412            boxStart.x = x - deltaX;
413            boxStart.y = y - deltaY;
414            boxEnd.x = x + deltaX;
415            boxEnd.y = y + deltaY;
416            flag = flag | Box_Enabled;
417            repaint();
418            flag = flag & (~Box_Enabled);
419        }
420    
421        public void setShapeSize(int shapeSize) {
422            this.shapeSize = shapeSize;
423        }
424    
425        public void setZoomingSize(int w, int h) {
426            zoomingWidth = w;
427            zoomingHeight = h;
428        }
429    
430        public Point2D.Double getMouseMovement() {
431            return mousePos;
432        }
433    
434        public void scaleImage(boolean scaled) {
435            if (scaled)
436                flag = flag | Scale_Image;
437            else
438                flag = flag & (~Scale_Image);
439        }
440    
441        public void setParent(JScrollPane parent) {
442            this.parent = parent;
443        }
444    
445        public void setPanelFlag(int flag) {
446            this.flag = flag;
447            if ((flag & 0x000f) != Axis_Enabled) {
448                origin.setLocation(0,0);
449                imageAdjustment.x = 0;
450                imageAdjustment.y = 0;
451            }
452        }
453    
454        public Point getOrigin() {
455            return origin;
456        }
457    
458        public void setPhases(ArrayList phases) {
459            this.phases = phases;
460            if (autoImage == null) return;
461            autoImage.setPhases(phases);
462            try {
463                image = autoImage.getImage();
464            } catch (NoDataPlotException e) {
465                // fall through
466            }
467        }
468    
469        public void addString(int x, int y, String content) {
470            Object[] aString = new Object[3];
471    
472            aString[0] = new Integer(x);
473            aString[1] = new Integer(y);
474            aString[2] = content;
475            stringList.add(aString);
476        }
477    
478        public void reset() {
479            stringList.clear();
480        }
481    
482        public int getFlag() {
483            return flag;
484        }
485    
486        public Object clone() {
487            AxesPanel o = new AxesPanel(flag);
488    
489            o.xName = xName;
490            o.yName = yName;
491            o.zoomingWidth = zoomingWidth;
492            o.zoomingHeight = zoomingHeight;
493            o.shapeSize = shapeSize;
494            return o;
495        }
496    
497        private void calcScaleFactors() {
498            int w = getWidth(), h = getHeight();
499            factorX = factorY = 1;
500            if ((flag&0xf0000000) == Scale_X)
501                factorX = (double)(w - imageAdjustment.x) / (double)(image.getWidth());
502            if ((flag&0x0f000000) == Scale_Y)
503                factorY = (double)(h - imageAdjustment.y) / (double)(image.getHeight());
504        }
505    }