001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.wicket.markup.html.link;
018:
019: import java.util.ArrayList;
020: import java.util.Iterator;
021: import java.util.List;
022:
023: import org.apache.wicket.IClusterable;
024: import org.apache.wicket.markup.ComponentTag;
025: import org.apache.wicket.markup.MarkupStream;
026: import org.apache.wicket.markup.html.WebMarkupContainer;
027:
028: /**
029: * An image map holds links with different hot-area shapes.
030: *
031: * @author Jonathan Locke
032: */
033: public final class ImageMap extends WebMarkupContainer {
034: private static final long serialVersionUID = 1L;
035:
036: /** list of shape links. */
037: private final List shapeLinks = new ArrayList();
038:
039: /**
040: * A shape that has a circle form.
041: */
042: private static final class CircleLink extends ShapeLink {
043: private static final long serialVersionUID = 1L;
044:
045: /** The circle's radius. */
046: private final int radius;
047:
048: /** Upper left x */
049: private final int x;
050:
051: /** Upper left y */
052: private final int y;
053:
054: /**
055: * Construct.
056: *
057: * @param x
058: * left upper x
059: * @param y
060: * left upper y
061: * @param radius
062: * the circles' radius
063: * @param link
064: * the link
065: */
066: public CircleLink(final int x, final int y, final int radius,
067: final Link link) {
068: super (link);
069: this .x = x;
070: this .y = y;
071: this .radius = radius;
072: }
073:
074: /**
075: * @see org.apache.wicket.markup.html.link.ImageMap.ShapeLink#getCoordinates()
076: */
077: String getCoordinates() {
078: return x + "," + y + "," + radius;
079: }
080:
081: /**
082: * @see org.apache.wicket.markup.html.link.ImageMap.ShapeLink#getType()
083: */
084: String getType() {
085: return "circle";
086: }
087: }
088:
089: /**
090: * A shape that has a free (polygon) form.
091: */
092: private static final class PolygonLink extends ShapeLink {
093: private static final long serialVersionUID = 1L;
094:
095: /** Its coordinates. */
096: private final int[] coordinates;
097:
098: /**
099: * Construct.
100: *
101: * @param coordinates
102: * the polygon coordinates
103: * @param link
104: * the link
105: */
106: public PolygonLink(final int[] coordinates, final Link link) {
107: super (link);
108: this .coordinates = coordinates;
109: }
110:
111: /**
112: * @see org.apache.wicket.markup.html.link.ImageMap.ShapeLink#getCoordinates()
113: */
114: String getCoordinates() {
115: final StringBuffer buffer = new StringBuffer();
116: for (int i = 0; i < coordinates.length; i++) {
117: buffer.append(coordinates[i]);
118:
119: if (i < (coordinates.length - 1)) {
120: buffer.append(',');
121: }
122: }
123: return buffer.toString();
124: }
125:
126: /**
127: * @see org.apache.wicket.markup.html.link.ImageMap.ShapeLink#getType()
128: */
129: String getType() {
130: return "polygon";
131: }
132: }
133:
134: /**
135: * A shape that has a rectangular form.
136: */
137: private static final class RectangleLink extends ShapeLink {
138: private static final long serialVersionUID = 1L;
139:
140: /** left upper x. */
141: private final int x1;
142:
143: /** right bottom x. */
144: private final int x2;
145:
146: /** left upper y. */
147: private final int y1;
148:
149: /** right bottom y. */
150: private final int y2;
151:
152: /**
153: * Construct.
154: *
155: * @param x1
156: * left upper x
157: * @param y1
158: * left upper y
159: * @param x2
160: * right bottom x
161: * @param y2
162: * right bottom y
163: * @param link
164: * the link
165: */
166: public RectangleLink(final int x1, final int y1, final int x2,
167: final int y2, final Link link) {
168: super (link);
169: this .x1 = x1;
170: this .y1 = y1;
171: this .x2 = x2;
172: this .y2 = y2;
173: }
174:
175: /**
176: * @see org.apache.wicket.markup.html.link.ImageMap.ShapeLink#getCoordinates()
177: */
178: String getCoordinates() {
179: return x1 + "," + y1 + "," + x2 + "," + y2;
180: }
181:
182: /**
183: * @see org.apache.wicket.markup.html.link.ImageMap.ShapeLink#getType()
184: */
185: String getType() {
186: return "rectangle";
187: }
188: }
189:
190: /**
191: * Base class for shaped links.
192: */
193: private static abstract class ShapeLink implements IClusterable {
194: /** The link. */
195: private final Link link;
196:
197: /**
198: * Constructor.
199: *
200: * @param link
201: * The link
202: */
203: public ShapeLink(final Link link) {
204: this .link = link;
205: }
206:
207: /**
208: * The shape as a string using the given request cycle; will be used for
209: * rendering.
210: *
211: * @return The shape as a string
212: */
213: public String toString() {
214: // Add any popup script
215: final String popupJavaScript;
216:
217: if (link.getPopupSettings() != null) {
218: popupJavaScript = link.getPopupSettings()
219: .getPopupJavaScript();
220: } else {
221: popupJavaScript = null;
222: }
223:
224: return "<area shape=\""
225: + getType()
226: + "\""
227: + " coords=\""
228: + getCoordinates()
229: + "\""
230: + " href=\""
231: + link.getURL()
232: + "\""
233: // Output the markup ID if that was specified, so we can link tooltips, etc. to it.
234: + (link.getOutputMarkupId() ? " id=\""
235: + link.getMarkupId() + "\"" : "")
236: + ((popupJavaScript == null) ? ""
237: : (" onClick = \"" + popupJavaScript + "\""))
238: + ">";
239: }
240:
241: /**
242: * Gets the coordinates of the shape.
243: *
244: * @return The coordinates of the shape
245: */
246: abstract String getCoordinates();
247:
248: /**
249: * Gets the shape type.
250: *
251: * @return the shape type
252: */
253: abstract String getType();
254: }
255:
256: /**
257: * Constructor.
258: *
259: * @param id
260: * See Component
261: */
262: public ImageMap(final String id) {
263: super (id);
264: }
265:
266: /**
267: * Adds a circle link.
268: *
269: * @param x1
270: * top left x
271: * @param y1
272: * top left y
273: * @param radius
274: * the radius
275: * @param link
276: * the link
277: * @return This
278: */
279: public ImageMap addCircleLink(final int x1, final int y1,
280: final int radius, final Link link) {
281: add(link);
282: shapeLinks.add(new CircleLink(x1, y1, radius, link));
283: return this ;
284: }
285:
286: /**
287: * Adds a polygon link.
288: *
289: * @param coordinates
290: * the coordinates for the polygon
291: * @param link
292: * the link
293: * @return This
294: */
295: public ImageMap addPolygonLink(final int[] coordinates,
296: final Link link) {
297: add(link);
298: shapeLinks.add(new PolygonLink(coordinates, link));
299: return this ;
300: }
301:
302: /**
303: * Adds a rectangular link.
304: *
305: * @param x1
306: * top left x
307: * @param y1
308: * top left y
309: * @param x2
310: * bottom right x
311: * @param y2
312: * bottom right y
313: * @param link
314: * @return This
315: */
316: public ImageMap addRectangleLink(final int x1, final int y1,
317: final int x2, final int y2, final Link link) {
318: add(link);
319: shapeLinks.add(new RectangleLink(x1, y1, x2, y2, link));
320: return this ;
321: }
322:
323: /**
324: * Renders this component.
325: *
326: * @see org.apache.wicket.Component#onRender(MarkupStream)
327: */
328: protected void onRender(final MarkupStream markupStream) {
329: // Get mutable copy of next tag
330: final ComponentTag tag = markupStream.getTag().mutable();
331:
332: // Must be an img tag
333: checkComponentTag(tag, "img");
334:
335: // Set map name to path
336: tag.put("usemap", "#" + getPath());
337:
338: // Write out the tag
339: renderComponentTag(tag);
340: markupStream.next();
341:
342: // Write out the image map
343: final StringBuffer imageMap = new StringBuffer();
344:
345: imageMap.append("\n<map name=\"").append(getPath()).append(
346: "\"> ");
347:
348: for (Iterator iterator = shapeLinks.iterator(); iterator
349: .hasNext();) {
350: final ShapeLink shapeLink = (ShapeLink) iterator.next();
351: imageMap.append('\n');
352: imageMap.append(shapeLink.toString());
353:
354: // Tell framework that this link was actually rendered
355: getPage().componentRendered(shapeLink.link);
356: }
357:
358: imageMap.append("\n</map>");
359: getResponse().write(imageMap.toString());
360: }
361: }
|