001: /*
002: * Copyright 2005 jWic Group (http://www.jwic.de)
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: *
016: * de.jwic.controls.ImageControl
017: * Created on 20.10.2004
018: * $Id: ImageControl.java,v 1.4 2007/05/08 20:14:27 cosote Exp $
019: */
020: package de.jwic.controls;
021:
022: /**
023: * @author Bornemann
024: *
025: */
026:
027: import java.io.ByteArrayOutputStream;
028: import java.io.IOException;
029: import java.io.OutputStream;
030: import java.io.Serializable;
031: import java.util.ArrayList;
032: import java.util.List;
033:
034: import javax.servlet.http.HttpServletRequest;
035: import javax.servlet.http.HttpServletResponse;
036:
037: import de.jwic.base.ControlContainer;
038: import de.jwic.base.IControlContainer;
039: import de.jwic.base.IResourceControl;
040:
041: /**
042: * Default IImageControl implementation that support linked map.
043: * ImageControl.vtl uses jWic ajax update listener to replace the image without flicker.
044: *
045: * IE 6 has a bug when working with img tag using a map:
046: * An update to the map without updating its img also crashes the IE6!
047: *
048: * @author jbornema
049: *
050: */
051: public abstract class ImageControl extends ControlContainer implements
052: IResourceControl {
053:
054: /**
055: * Shap represents a html area for maps. Supported types are
056: * SHAPE_TYPE_RECT, SHAPE_TYPE_CIRCLE and SHAPE_TYPE_POLY.
057: * Coords are comma separated, e.g. "x,y,r" for circles.
058: */
059: public class Shape implements Serializable {
060: private static final long serialVersionUID = 1L;
061: String type = null;
062: String coords = null;
063: String url = null;
064: String title = null;
065:
066: Shape(String type, String coords, String title, String url) {
067: this .type = type;
068: this .coords = coords;
069: this .url = url;
070: this .title = title;
071: }
072:
073: public String getType() {
074: return type;
075: }
076:
077: public String getCoords() {
078: return coords;
079: }
080:
081: public String getURL() {
082: return url;
083: }
084:
085: public String getTitle() {
086: return title;
087: }
088: };
089:
090: public final static String MIME_TYPE_PNG = "image/png";
091: public final static String MIME_TYPE_JPG = "image/jpg";
092: public final static String MIME_TYPE_GIF = "image/gif";
093:
094: public final static String SHAPE_TYPE_RECT = "rect";
095: public final static String SHAPE_TYPE_CIRCLE = "circle";
096: public final static String SHAPE_TYPE_POLY = "poly";
097:
098: protected List shapes;
099: private transient ByteArrayOutputStream imageOutputStream;
100: protected String mimeType;
101: protected int width;
102: protected int height;
103: protected String infoMessage;
104: protected boolean createUniqueURL;
105: protected boolean hidden;
106:
107: /**
108: * @param container
109: * @param name
110: */
111: public ImageControl(IControlContainer container, String name) {
112: super (container, name);
113:
114: // init variables
115: shapes = null;
116: mimeType = MIME_TYPE_JPG;
117: width = -1;
118: height = -1;
119: infoMessage = null;
120: createUniqueURL = false;
121: hidden = false;
122:
123: // set default template
124: setTemplateName(ImageControl.class.getName());
125: }
126:
127: /**
128: * The filename is used in the servlet response and in
129: * the html rendering.
130: * @return The filename for the created image.
131: */
132: public abstract String getFilename();
133:
134: /**
135: * Return the ByteArrayOutputStream renderImage() must write the binary
136: * image data into. Should call reset() to it before creating the image
137: * data again.
138: * @return
139: */
140: public ByteArrayOutputStream getImageOutputStream() {
141: if (imageOutputStream == null) {
142: imageOutputStream = new ByteArrayOutputStream();
143: }
144: return imageOutputStream;
145: }
146:
147: /**
148: * Renders the image data to imageOutputStream.
149: * Don't forget to set the appropiate mime type and call
150: * ByteArrayOutputStream.reset() before generating the image data again.
151: * @throws IOException
152: */
153: public abstract void renderImage() throws IOException;
154:
155: /**
156: * Renders the image data to the writer.
157: * @param writer
158: * @return Mime encoding type like "image/jpg" or "image/gif"
159: * @throws IOException
160: */
161: public String renderImage(OutputStream out) throws IOException {
162: ByteArrayOutputStream data = getImageOutputStream();
163: if (imageOutputStream.size() == 0) {
164: // ups, no output? renderImage() not called?
165: renderImage();
166: }
167: data.writeTo(out);
168: return mimeType;
169: }
170:
171: /* (non-Javadoc)
172: * @see de.jwic.base.IResourceControl#attachResource(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
173: */
174: public void attachResource(HttpServletRequest req,
175: HttpServletResponse res) throws IOException {
176: String type = renderImage(res.getOutputStream());
177: res.setContentType(type);
178: res.setHeader("Content-Disposition", "filename="
179: + getFilename());
180: /*res.setHeader("Expires", "0");
181: res.setHeader ("Cache-Control", "no-cache");
182: res.setHeader ("Pragma", "no-cache");*/
183: }
184:
185: /* (non-Javadoc)
186: * @see de.jwic.base.IControl#actionPerformed(java.lang.String, java.lang.String)
187: */
188: public void actionPerformed(String actionId, String parameter) {
189: // no action implemented
190: }
191:
192: /**
193: * Return Collection of Shape objects that had been added with addShape(...).
194: * @return
195: */
196: public List getShapes() {
197: if (shapes == null) {
198: shapes = new ArrayList();
199: }
200: return shapes;
201: }
202:
203: /**
204: * Adds a shape of type SHAPE_TYPE_RECT, ..._CIRLCE or ..._POLY with url and title.
205: * If url is null no "clickable" link is added.
206: * Depending on the shape type the coords follow different syntax:
207: * SHAPE_TYPE_RECT: "x1,y1,x2,y2"
208: * SHAPE_TYPE_CIRCLE: "x,y,r"
209: * SHAPE_TYPE_POLY: "x1,y1[,x2,y2[,...]]"
210: * @param type
211: * @param coords
212: * @param url
213: * @param title
214: */
215: public void addShape(String type, String coords, String title,
216: String url) {
217: // add new Shapes always at top, so last added Shape is rendered first
218: getShapes().add(0, new Shape(type, coords, title, url));
219: }
220:
221: /**
222: * Same as addShape(type, coords, title, null)
223: * @param type
224: * @param coords
225: * @param title
226: */
227: public void addShape(String type, String coords, String title) {
228: addShape(type, coords, title, null);
229: }
230:
231: /**
232: * Return the mime type for this image, like MIME_TYPE_JPG.
233: * @return
234: */
235: public String getMimeType() {
236: return mimeType;
237: }
238:
239: /**
240: * Set the mime type for this image, like MIME_TYPE_JPG.
241: * @param mimeType
242: */
243: public void setMimeType(String mimeType) {
244: this .mimeType = mimeType;
245: }
246:
247: /* (non-Javadoc)
248: * @see de.jwic.base.IControl#setRequireRedraw(boolean)
249: */
250: public void setRequireRedraw(boolean requireRedraw) {
251: super .setRequireRedraw(requireRedraw);
252: if (requireRedraw) {
253: // clear image data
254: getImageOutputStream().reset();
255: }
256: }
257:
258: /**
259: * Return the image width in pixel.
260: * @return
261: */
262: public int getWidth() {
263: return width;
264: }
265:
266: /**
267: * Set the image width in pixel.
268: * @param width
269: */
270: public void setWidth(int width) {
271: if (this .width != width) {
272: setRequireRedraw(true);
273: }
274: this .width = width;
275: }
276:
277: /**
278: * Return the image height in pixel.
279: * @return
280: */
281: public int getHeight() {
282: return height;
283: }
284:
285: /**
286: * Set the image height in pixel.
287: * @param height
288: */
289: public void setHeight(int height) {
290: if (this .height != height) {
291: setRequireRedraw(true);
292: }
293: this .height = height;
294: }
295:
296: /**
297: * Create a URL to this image.
298: * Current milliseconds is part of that URL is createUniqueURL is set.
299: * @return
300: */
301: public String createImageURL() {
302: return getSessionContext().getCallBackURL()
303: + "&_resreq=1&controlId="
304: + ImageControl.this .getControlID()
305: + (createUniqueURL ? "&time="
306: + System.currentTimeMillis() + "&" : "&")
307: + getFilename();
308: }
309:
310: /**
311: * Return the info message that is used for img title attribute and is
312: * also displayed in window.status.
313: * @return
314: */
315: public String getInfoMessage() {
316: return infoMessage;
317: }
318:
319: /**
320: * Set the info message that is used for img title attribute and is
321: * also displayed in window.status.
322: * @param infoMessage
323: */
324: public void setInfoMessage(String infoMessage) {
325: this .infoMessage = infoMessage;
326: }
327:
328: /**
329: * Return true if on every createUniqueURL() a new URL is created.
330: * Default is false.
331: * @return
332: */
333: public boolean isCreateUniqueURL() {
334: return createUniqueURL;
335: }
336:
337: /**
338: * Set if on every createUniqueURL() a new URL is created.
339: * Default is false.
340: * @param createUniqueURL
341: */
342: public void setCreateUniqueURL(boolean createUniqueURL) {
343: this .createUniqueURL = createUniqueURL;
344: }
345:
346: /**
347: * Return true if control should be rendered with no content.
348: * Used to render the JavaScript if control should be invisible.
349: * Should be used instead of visible attribute.
350: * @return
351: */
352: public boolean isHidden() {
353: return hidden;
354: }
355:
356: /**
357: * Set if control should be rendered with no content.
358: * Used to render the JavaScript if control should be invisible.
359: * Should be used instead of visible attribute.
360: * @param hidden
361: */
362: public void setHidden(boolean hidden) {
363: this .hidden = hidden;
364: setRequireRedraw(true);
365: }
366: }
|