001package horstmann.ch08_umleditor;
002import java.awt.geom.Point2D;
003import java.awt.geom.Rectangle2D;
004import java.util.ArrayList;
005
006/**
007   A style for a segmented line that indicates the number
008   and sequence of bends.
009 */
010public enum BentStyle
011{
012        STRAIGHT, HV, VH, HVH, VHV;
013
014        /**
015      Gets the points at which a line joining two rectangles
016      is bent according to this bent style.
017      @param start the starting rectangle
018      @param end the ending rectangle
019      @return an array list of points at which to bend the
020      segmented line joining the two rectangles
021         */
022        public ArrayList<Point2D> getPath(Rectangle2D start, Rectangle2D end)
023        {
024                ArrayList<Point2D> r = getPath(this, start, end);
025                if (r != null) return r;
026
027                if (this == HVH) r = getPath(VHV, start, end);
028                else if (this == VHV) r = getPath(HVH, start, end);
029                else if (this == HV) r = getPath(VH, start, end);
030                else if (this == VH) r = getPath(HV, start, end);
031                if (r != null) return r;
032
033                return getPath(STRAIGHT, start, end);
034        }
035
036        /**
037      Gets the four connecting points at which a bent line
038      connects to a rectangle.
039         */
040        private static Point2D[] connectionPoints(Rectangle2D r)
041        {
042                Point2D[] a = new Point2D[4];
043                a[0] = new Point2D.Double(r.getX(), r.getCenterY());
044                a[1] = new Point2D.Double(r.getMaxX(), r.getCenterY());
045                a[2] = new Point2D.Double(r.getCenterX(), r.getY());
046                a[3] = new Point2D.Double(r.getCenterX(), r.getMaxY());
047                return a;
048        }
049
050        /**
051      Gets the points at which a line joining two rectangles
052      is bent according to a bent style.
053      @return an array list of points at which to bend the
054      segmented line joining the two rectangles
055         */
056        private static ArrayList<Point2D> getPath(BentStyle bent,
057                        Rectangle2D s, Rectangle2D e)
058        {
059                ArrayList<Point2D> r = new ArrayList<Point2D>();
060                if (bent == STRAIGHT)
061                {
062                        Point2D[] a = connectionPoints(s);
063                        Point2D[] b = connectionPoints(e);
064                        Point2D p = a[0];
065                        Point2D q = b[0];
066                        double distance = p.distance(q);
067                        //for (int i = 0; i < a.length; i++)
068                        for (Point2D point1 : a)
069                                //for (int j = 0; j < b.length; j++)
070                                for (Point2D point2 : b)
071                                {
072                                        double d = point1.distance(point2);
073                                        if (d < distance)
074                                        {
075                                                p = point1; q = point2;
076                                                distance = d;
077                                        }
078                                }
079                        r.add(p);
080                        r.add(q);
081                }
082                else if (bent == HV)
083                {
084                        double x1;
085                        double x2 = e.getCenterX();
086                        double y1 = s.getCenterY();
087                        double y2;
088                        if (x2 + MIN_SEGMENT <= s.getX())
089                                x1 = s.getX();
090                        else if (x2 - MIN_SEGMENT >= s.getMaxX())
091                                x1 = s.getMaxX();
092                        else return null;
093                        if (y1 + MIN_SEGMENT <= e.getY())
094                                y2 = e.getY();
095                        else if (y1 - MIN_SEGMENT >= e.getMaxY())
096                                y2 = e.getMaxY();
097                        else return null;
098                        r.add(new Point2D.Double(x1, y1));
099                        r.add(new Point2D.Double(x2, y1));
100                        r.add(new Point2D.Double(x2, y2));
101                }
102                else if (bent == VH)
103                {
104                        double x1 = s.getCenterX();
105                        double x2;
106                        double y1;
107                        double y2 = e.getCenterY();
108                        if (x1 + MIN_SEGMENT <= e.getX())
109                                x2 = e.getX();
110                        else if (x1 - MIN_SEGMENT >= e.getMaxX())
111                                x2 = e.getMaxX();
112                        else return null;
113                        if (y2 + MIN_SEGMENT <= s.getY())
114                                y1 = s.getY();
115                        else if (y2 - MIN_SEGMENT >= s.getMaxY())
116                                y1 = s.getMaxY();
117                        else return null;
118                        r.add(new Point2D.Double(x1, y1));
119                        r.add(new Point2D.Double(x1, y2));
120                        r.add(new Point2D.Double(x2, y2));
121                }
122                else if (bent == HVH)
123                {
124                        double x1;
125                        double x2;
126                        double y1 = s.getCenterY();
127                        double y2 = e.getCenterY();
128                        if (s.getMaxX() + 2 * MIN_SEGMENT <= e.getX())
129                        {
130                                x1 = s.getMaxX();
131                                x2 = e.getX();
132                        }
133                        else if (e.getMaxX() + 2 * MIN_SEGMENT <= s.getX())
134                        {
135                                x1 = s.getX();
136                                x2 = e.getMaxX();
137                        }
138                        else return null;
139                        if (Math.abs(y1 - y2) <= MIN_SEGMENT)
140                        {
141                                r.add(new Point2D.Double(x1, (y1 + y2) / 2));
142                                r.add(new Point2D.Double(x2, (y1 + y2) / 2));
143                        }
144                        else
145                        {
146                                r.add(new Point2D.Double(x1, y1));
147                                r.add(new Point2D.Double((x1 + x2) / 2, y1));
148                                r.add(new Point2D.Double((x1 + x2) / 2, y2));
149                                r.add(new Point2D.Double(x2, y2));
150                        }
151                }
152                else if (bent == VHV)
153                {
154                        double x1 = s.getCenterX();
155                        double x2 = e.getCenterX();
156                        double y1;
157                        double y2;
158                        if (s.getMaxY() + 2 * MIN_SEGMENT <= e.getY())
159                        {
160                                y1 = s.getMaxY();
161                                y2 = e.getY();
162                        }
163                        else if (e.getMaxY() + 2 * MIN_SEGMENT <= s.getY())
164                        {
165                                y1 = s.getY();
166                                y2 = e.getMaxY();
167
168                        }
169                        else return null;
170                        if (Math.abs(x1 - x2) <= MIN_SEGMENT)
171                        {
172                                r.add(new Point2D.Double((x1 + x2) / 2, y1));
173                                r.add(new Point2D.Double((x1 + x2) / 2, y2));
174                        }
175                        else
176                        {
177                                r.add(new Point2D.Double(x1, y1));
178                                r.add(new Point2D.Double(x1, (y1 + y2) / 2));
179                                r.add(new Point2D.Double(x2, (y1 + y2) / 2));
180                                r.add(new Point2D.Double(x2, y2));
181                        }
182                }
183                else return null;
184                return r;
185        }
186
187        private static final int MIN_SEGMENT = 10;
188}