001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 */
021
022package org.biojava.bio.gui.sequence;
023
024import java.io.Serializable;
025import java.net.URL;
026import java.util.ArrayList;
027import java.util.Iterator;
028import java.util.List;
029
030/**
031 * <code>ImageMap</code> represents a collection of image map
032 * hotspots. It does not represent the raster image itself.
033 *
034 * @author Keith James
035 * @author Greg Cox
036 * @since 1.3
037 */
038public interface ImageMap
039{
040    /**
041     * <code>RECT</code> indicates a rectangular image map hotspot.
042     */
043    public static final String RECT = "rect";
044
045    /**
046     * <code>CIRCLE</code> indicates a circular image map hotspot.
047     */
048    public static final String CIRCLE = "circle";
049
050    /**
051     * <code>POLY</code> indicates a polygonal image map hotspot.
052     */
053    public static final String POLY = "poly";
054
055    /**
056     * <code>addHotSpot</code> adds a hotspot to the map.
057     *
058     * @param hotSpot a <code>HotSpot</code>.
059     */
060    public void addHotSpot(HotSpot hotSpot);
061
062    /**
063     * <code>hotSpots</code> iterates over the hotspots in the map
064     *
065     * @return an <code>Iterator</code>.
066     */
067    public Iterator hotSpots();
068
069    /**
070     * <p><code>HotSpot</code>s represent an image map hotspot. For
071     * example (in server-side map format):</p>
072     *
073     * <p>rect http://www.biojava.org 0,0 100,20</p>
074     *
075     * <p>A user object may be set for each hot spot. This would
076     * typically contain extra data used to construct a representation
077     * of the hotspot in a document or application. For example, in an
078     * image map representing Blast search results the user object
079     * could be a sequence in a database. In an HTML document the user
080     * object could be used to assign values to actions such as
081     * mouseover.</p>
082     */
083    public static final class HotSpot implements Serializable
084    {
085        private String type;
086        private URL url;
087        private Integer [] coordinates;
088        private Object userObject;
089
090        /**
091         * Creates a new <code>HotSpot</code> with a null user object.
092         *
093         * @param type a <code>String</code> of hotspot. The only
094         * valid arguments are ImageMap.RECT, ImageMap.CIRCLE or
095         * ImageMap.POLY (checked by object reference equalty);
096         * @param url a <code>URL</code> target.
097         * @param coordinates an <code>Integer []</code> array of
098         * hotspot coordinates, in order.
099         */
100        public HotSpot(String type, URL url, Integer [] coordinates)
101        {
102            if (! (type == RECT || type == CIRCLE || type == POLY))
103                throw new IllegalArgumentException("Failed to create HotSpot. Constructor was passed an invalid type '"
104                                                   + type + "'");
105
106            if (! (coordinates.length % 2 == 0))
107                throw new IllegalArgumentException("Failed to create HotSpot. The coordinates array contained an odd number of points");
108
109            this.type = type;
110            this.url = url;
111            this.coordinates = coordinates;
112        }
113
114        /**
115         * Creates a new <code>HotSpot</code>.
116         *
117         * @param type a <code>String</code> of hotspot. The only
118         * valid arguments are ImageMap.RECT, ImageMap.CIRCLE or
119         * ImageMap.POLY (checked by object reference equalty);
120         * @param url a <code>URL</code> target.
121         * @param coordinates an <code>Integer []</code> array of
122         * hotspot coordinates, in order.
123         * @param userObject an <code>Object</code>
124         */
125        public HotSpot(String type, URL url, Integer [] coordinates, Object userObject)
126        {
127            this(type, url, coordinates);
128            this.userObject = userObject;
129        }
130
131        /**
132         * <code>getType</code> returns the type of hotspot.
133         *
134         * @return a <code>String</code>.
135         */
136        public String getType()
137        {
138            return type;
139        }
140
141        /**
142         * <code>getURL</code> returns the hotspot URL.
143         *
144         * @return a <code>URL</code>.
145         */
146        public URL getURL()
147        {
148            return url;
149        }
150
151        /**
152         * <code>getCoordinates</code> returns the hotspot coordinates.
153         *
154         * @return an <code>Integer []</code> array.
155         */
156        public Integer [] getCoordinates()
157        {
158            return coordinates;
159        }
160
161        /**
162         * <code>getUserObject</code> returns the current user object
163         * (or null).
164         *
165         * @return an <code>Object</code>.
166         */
167        public Object getUserObject()
168        {
169            return userObject;
170        }
171
172        /**
173         * <code>setUserObject</code> sets the user object.
174         *
175         * @param userObject an <code>Object</code>.
176         */
177        public void setUserObject(Object userObject)
178        {
179            this.userObject = userObject;
180        }
181
182        public String toString()
183        {
184            return  "HotSpot to " + url.toString();
185        }
186    }
187
188    /**
189     * <code>ClientSide</code> represents a client-side style image
190     * map.
191     */
192    public static class ClientSide implements ImageMap, Serializable
193    {
194        private String name;
195        private List hotSpots;
196
197        /**
198         * Creates a new <code>ClientSide</code> image map.
199         *
200         * @param name a <code>String</code> name by which the map
201         * will be known.
202         */
203        public ClientSide(String name)
204        {
205            this.name = name;
206            hotSpots = new ArrayList();
207        }
208
209        public void addHotSpot(HotSpot hotSpot)
210        {
211            hotSpots.add(hotSpot);
212        }
213
214        public Iterator hotSpots()
215        {
216            return hotSpots.iterator();
217        }
218
219        public String toString()
220        {
221            StringBuffer sb = new StringBuffer();
222
223            sb.append("<map name=");
224            sb.append("\"");
225            sb.append(name);
226            sb.append("\">\n");
227
228            for (Iterator hi = hotSpots.iterator(); hi.hasNext();)
229            {
230                HotSpot hs = (HotSpot) hi.next();
231                Integer [] coords = hs.getCoordinates();
232
233                sb.append("<area shape=\"");
234                sb.append(hs.getType());
235                sb.append("\" href=\"");
236                sb.append(hs.getURL().toString());
237                sb.append("\" coords=\"");
238
239                int lastDelim = coords.length - 1;
240                char delim = ',';
241
242                for (int i = 0; i < coords.length; i++)
243                {
244                    sb.append(coords[i]);
245
246                    if (i <= lastDelim)
247                        sb.append(delim);
248                }
249                sb.append("\">\n");
250            }
251
252            sb.append("</map>");
253
254            return sb.substring(0);
255        }
256    }
257
258    /**
259     * <code>ServerSide</code> represents a server-side style image
260     * map.
261     */
262    public static class ServerSide implements ImageMap, Serializable
263    {
264        private List hotSpots;
265
266        /**
267         * Creates a new <code>ServerSide</code> image map.
268         */
269        public ServerSide()
270        {
271            hotSpots = new ArrayList();
272        }
273
274        public void addHotSpot(HotSpot hotSpot)
275        {
276            hotSpots.add(hotSpot);
277        }
278
279        public Iterator hotSpots()
280        {
281            return hotSpots.iterator();
282        }
283
284        public String toString()
285        {
286            StringBuffer sb = new StringBuffer();
287
288            for (Iterator hi = hotSpots.iterator(); hi.hasNext();)
289            {
290                HotSpot hs = (HotSpot) hi.next();
291                Integer [] coords = hs.getCoordinates();
292
293                sb.append(hs.getType());
294                sb.append(" ");
295                sb.append(hs.getURL().toString());
296                sb.append(" ");
297
298                for (int i = 0; i < (coords.length - 1); i += 2)
299                {
300                    sb.append(coords[i]);
301                    sb.append(",");
302                    sb.append(coords[i + 1]);
303                    sb.append(" ");
304                }
305            }
306
307            return sb.substring(0).trim();
308        }
309    }
310}