You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by jk...@apache.org on 2007/04/24 05:08:26 UTC
svn commit: r531707 - in /tapestry/tapestry4/trunk:
tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/
tapestry-contrib/src/test/org/apache/tapestry/contrib/services/
tapestry-examples/TimeTracker/ tapestry-examples/TimeTracker/src/co...
Author: jkuhnert
Date: Mon Apr 23 20:08:25 2007
New Revision: 531707
URL: http://svn.apache.org/viewvc?view=rev&rev=531707
Log:
Added a few more abilities to the rounded corner service - like drop shadows.
Added:
tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/ShadowRenderer.java (with props)
tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/
tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/Locale.java (with props)
tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/Locale.jwc
Modified:
tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/RoundedCornerGenerator.java
tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/RoundedCornerService.java
tapestry/tapestry4/trunk/tapestry-contrib/src/test/org/apache/tapestry/contrib/services/TestRoundedCornerService.java
tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/pom.xml
tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/LocaleList.html
tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/WEB-INF/timetracker.application
Modified: tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/RoundedCornerGenerator.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/RoundedCornerGenerator.java?view=diff&rev=531707&r1=531706&r2=531707
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/RoundedCornerGenerator.java (original)
+++ tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/RoundedCornerGenerator.java Mon Apr 23 20:08:25 2007
@@ -1,10 +1,13 @@
package org.apache.tapestry.contrib.services.impl;
+import org.apache.hivemind.util.Defense;
+
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.geom.Arc2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;
@@ -13,6 +16,16 @@
*/
public class RoundedCornerGenerator {
+ public static final String TOP_LEFT = "tl";
+ public static final String TOP_RIGHT = "tr";
+ public static final String BOTTOM_LEFT = "bl";
+ public static final String BOTTOM_RIGHT = "br";
+
+ public static final String LEFT = "left";
+ public static final String RIGHT = "right";
+ public static final String TOP = "top";
+ public static final String BOTTOM = "bottom";
+
// css2 color spec - http://www.w3.org/TR/REC-CSS2/syndata.html#color-units
private static final Map _cssSpecMap = new HashMap();
@@ -33,73 +46,345 @@
_cssSpecMap.put("teal", new Color(0,128,128));
_cssSpecMap.put("white", Color.white);
_cssSpecMap.put("yellow", Color.yellow);
+
+ ImageIO.setUseCache(false);
}
- public static final String TOP_LEFT = "tl";
- public static final String TOP_RIGHT = "tr";
- public static final String BOTTOM_LEFT = "bl";
- public static final String BOTTOM_RIGHT = "br";
+ private static Color SHADOW_COLOR = new Color(0x000000);
- // holds pre-built binaries for previously generated colors
- private Map _imageCache = new HashMap();
+ private static final float DEFAULT_OPACITY = 0.5f;
- public byte[] buildCorner(String color, String backgroundColor, int width, int height, String angle)
+ private static final float ANGLE_TOP_LEFT = 90f;
+ private static final float ANGLE_TOP_RIGHT = 0f;
+ private static final float ANGLE_BOTTOM_LEFT = 180f;
+ private static final float ANGLE_BOTTOM_RIGHT = 270f;
+
+ public BufferedImage buildCorner(String color, String backgroundColor, int width, int height,
+ String angle, int shadowWidth, float endOpacity)
throws Exception
{
- String hashKey = color + backgroundColor + width + height + angle;
+ float startAngle = getStartAngle(angle);
+ Color bgColor = backgroundColor == null ? null : decodeColor(backgroundColor);
+
+ if (shadowWidth <= 0) {
+
+ BufferedImage arc = drawArc(color, backgroundColor, width, height, angle, false, -1);
+ BufferedImage ret = arc;
+
+ if (bgColor != null) {
+
+ ret = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g2 = (Graphics2D)ret.createGraphics();
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ Arc2D.Float arcArea = new Arc2D.Float(0, 0, width, height, startAngle, 90, Arc2D.PIE);
+
+ g2.setColor(bgColor);
+ g2.fill(arcArea.getBounds2D());
+
+ g2.drawImage(arc, 0, 0, null);
+
+ g2.dispose();
+ }
- byte[] ret = (byte[])_imageCache.get(hashKey);
- if (ret != null)
return ret;
-
+ }
+
+ BufferedImage mask = drawArc(color, backgroundColor, width, height, angle, true, shadowWidth);
+ BufferedImage arc = drawArc(color, backgroundColor, width, height, angle, false, shadowWidth);
+
+ float startX = 0;
+ float startY = 0;
+ int shadowSize = shadowWidth * 2;
+ float canvasWidth = width + (shadowSize * 2);
+ float canvasHeight = height + (shadowSize * 2);
+
+ if (startAngle == ANGLE_BOTTOM_LEFT) {
+
+ startY -= (shadowSize * 2);
+
+ } else if (startAngle == ANGLE_TOP_RIGHT) {
+
+ startX -= shadowSize * 2;
+
+ } else if (startAngle == ANGLE_BOTTOM_RIGHT) {
+
+ startX -= shadowSize * 2;
+ startY -= shadowSize * 2;
+ // startX -= shadowSize;
+ // startY -= shadowSize;
+ }
+
+ BufferedImage ret = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g2 = (Graphics2D)ret.createGraphics();
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ Arc2D.Float arcArea = new Arc2D.Float(startX, startY, canvasWidth, canvasHeight, startAngle, 90, Arc2D.PIE);
+
+ if (bgColor != null) {
+
+ g2.setColor(bgColor);
+ g2.fill(arcArea.getBounds2D());
+ }
+
+ BufferedImage shadow = drawArcShadow(mask, color, backgroundColor, width, height, angle, shadowWidth, endOpacity);
+
+ g2.setClip(arcArea);
+ g2.drawImage(shadow, 0, 0, null);
+
+ g2.setClip(null);
+ g2.drawImage(arc, 0, 0, null);
+
+ return ret;
+ }
+
+ BufferedImage drawArc(String color, String backgroundColor, int width, int height, String angle, boolean masking, int shadowWidth)
+ {
Color arcColor = decodeColor(color);
Color bgColor = backgroundColor == null ? null : decodeColor(backgroundColor);
float startAngle = getStartAngle(angle);
- BufferedImage img = new BufferedImage( width, height, BufferedImage.TYPE_INT_ARGB);
- Graphics2D g2 = (Graphics2D) img.createGraphics();
+ int canvasWidth = width;
+ int canvasHeight = height;
+ float startX = 0;
+ float startY = 0;
+ int shadowSize = 0;
- Arc2D.Float fillArea = new Arc2D.Float(0f, 0f, (float)width, (float)height, startAngle, 90, Arc2D.PIE);
-
- // fill background color
+ if (shadowWidth > 0 && !masking) {
- if (bgColor != null) {
-
- g2.setClip(fillArea.getBounds2D());
- g2.setColor(bgColor);
- g2.fillRect(0, 0, width, height);
+ shadowSize = shadowWidth * 2;
+ canvasWidth += shadowSize * 2;
+ canvasHeight += shadowSize * 2;
+
+ if (startAngle == ANGLE_TOP_LEFT) {
+
+ startX += shadowSize;
+ startY += shadowSize;
+
+ } else if (startAngle == ANGLE_BOTTOM_LEFT) {
+
+ startX += shadowSize;
+ startY -= shadowSize;
+
+ } else if (startAngle == ANGLE_TOP_RIGHT) {
+
+ startX -= shadowSize;
+ startY += shadowSize;
+
+ } else if (startAngle == ANGLE_BOTTOM_RIGHT) {
+
+ startX -= shadowSize;
+ startY -= shadowSize;
+ }
}
- // draw arc
+ BufferedImage img = new BufferedImage( canvasWidth, canvasHeight, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g2 = (Graphics2D) img.createGraphics();
+
+ float extent = 90;
+ if (masking) {
+
+ extent = 120;
+ startAngle -= 20;
+ }
- g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ Arc2D.Float fillArea = new Arc2D.Float(startX, startY, width, height, startAngle, extent, Arc2D.PIE);
+ // draw arc
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
g2.setColor(arcColor);
g2.setComposite(AlphaComposite.Src);
g2.fill(fillArea);
+
+ g2.dispose();
+
+ return img;
+ }
+
+ BufferedImage drawArcShadow(BufferedImage mask, String color, String backgroundColor, int width, int height,
+ String angle, int shadowWidth, float endOpacity)
+ {
+ float startAngle = getStartAngle(angle);
+ int shadowSize = shadowWidth * 2;
+ int sampleY = 0;
+ int sampleX = 0;
+ int sampleWidth = width + shadowSize;
+ int sampleHeight = height + shadowSize;
+
+ if (startAngle == ANGLE_TOP_LEFT) {
+
+ } else if (startAngle == ANGLE_BOTTOM_LEFT) {
+
+ sampleWidth -= shadowSize;
+ sampleHeight = height;
+
+ sampleY += shadowSize;
+
+ } else if (startAngle == ANGLE_TOP_RIGHT) {
+
+ sampleWidth -= shadowSize;
+ sampleHeight -= shadowSize;
+
+ sampleX += shadowSize;
+ } else if (startAngle == ANGLE_BOTTOM_RIGHT) {
+
+ sampleWidth -= shadowSize;
+ sampleHeight -= shadowSize;
+
+ sampleX += shadowSize;
+ sampleY += shadowSize;
+ }
+
+ ShadowRenderer shadowRenderer = new ShadowRenderer(shadowWidth, endOpacity, SHADOW_COLOR);
+ BufferedImage dropShadow = shadowRenderer.createShadow(mask);
+
+ // draw shadow arc
+
+ BufferedImage img = new BufferedImage( (width * 4), (height * 4), BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g2 = (Graphics2D) img.createGraphics();
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2.setComposite(AlphaComposite.Src);
+ g2.drawImage(dropShadow, 0, 0, null);
+
g2.dispose();
- ByteArrayOutputStream bo = null;
+ return img.getSubimage(sampleX, sampleY, sampleWidth, sampleHeight);
+ }
- try {
- ImageIO.setUseCache(false);
+ public BufferedImage buildShadow(String backgroundColor, int width, int height,
+ float arcWidth, float arcHeight,
+ int shadowWidth, float endOpacity)
+ {
+ Color bgColor = backgroundColor == null ? null : decodeColor(backgroundColor);
+
+ BufferedImage mask = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g2 = mask.createGraphics();
+
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ RoundRectangle2D.Float fillArea = new RoundRectangle2D.Float(0, 0, width, height, arcHeight, arcWidth);
+ g2.fill(fillArea);
+ g2.dispose();
- bo = new ByteArrayOutputStream();
+ // clip shadow
- ImageIO.write(img, "gif", bo);
+ ShadowRenderer shadowRenderer = new ShadowRenderer(shadowWidth, endOpacity, SHADOW_COLOR);
+ BufferedImage dropShadow = shadowRenderer.createShadow(mask);
- ret = bo.toByteArray();
+ BufferedImage clipImg = new BufferedImage( width + (shadowWidth * 2), height + (shadowWidth * 2), BufferedImage.TYPE_INT_ARGB);
+ g2 = clipImg.createGraphics();
- _imageCache.put(hashKey, ret);
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+ g2.setComposite(AlphaComposite.Src);
- return ret;
+ RoundRectangle2D.Float clip = new RoundRectangle2D.Float(0, 0, width + (shadowWidth * 2), height + (shadowWidth * 2), arcHeight, arcWidth);
+ g2.setClip(clip);
+ g2.drawImage(dropShadow, 0, 0, null);
+ g2.dispose();
+
+ // draw everything
- } finally {
- if (bo != null) {
- bo.close();
- }
+ BufferedImage img = new BufferedImage( width + (shadowWidth * 2), height + (shadowWidth * 2), BufferedImage.TYPE_INT_ARGB);
+ g2 = img.createGraphics();
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ if (bgColor != null) {
+
+ fillArea = new RoundRectangle2D.Float(0, 0, width + (shadowWidth * 2), height + (shadowWidth * 2), arcHeight, arcWidth);
+ g2.setColor(bgColor);
+ g2.fill(fillArea.getBounds2D());
+ }
+
+ g2.drawImage(clipImg, 0, 0, null);
+
+ if (bgColor != null) {
+
+ fillArea = new RoundRectangle2D.Float(0, 0, width, height, arcHeight, arcWidth);
+ g2.setColor(bgColor);
+ g2.fill(fillArea);
+ }
+
+ g2.dispose();
+
+ return img;
+ }
+
+ public BufferedImage buildSideShadow(String side, int size, float opacity)
+ throws Exception
+ {
+ Defense.notNull(side, "side");
+
+ if (opacity <= 0)
+ opacity = DEFAULT_OPACITY;
+
+ int maskWidth = 0;
+ int maskHeight = 0;
+ int sampleY = 0;
+ int sampleX = 0;
+ int sampleWidth = 0;
+ int sampleHeight = 0;
+
+ if (LEFT.equals(side)) {
+
+ maskWidth = size * 4;
+ maskHeight = size * 4;
+ sampleY = maskHeight / 2;
+ sampleWidth = size * 2;
+ sampleHeight = 2;
+ } else if (RIGHT.equals(side)) {
+
+ maskWidth = size * 4;
+ maskHeight = size * 4;
+ sampleY = maskHeight / 2;
+ sampleX = maskWidth;
+ sampleWidth = size * 2;
+ sampleHeight = 2;
+ } else if (BOTTOM.equals(side)) {
+
+ maskWidth = size * 4;
+ maskHeight = size * 4;
+ sampleY = maskHeight;
+ sampleX = maskWidth / 2;
+ sampleWidth = 2;
+ sampleHeight = size * 2;
+ } else if (TOP.equals(side)) {
+
+ maskWidth = size * 4;
+ maskHeight = size * 4;
+ sampleY = 0;
+ sampleX = maskWidth / 2;
+ sampleWidth = 2;
+ sampleHeight = size * 2;
}
+
+ BufferedImage mask = new BufferedImage( maskWidth, maskHeight, BufferedImage.TYPE_INT_ARGB);
+ Graphics2D g2 = (Graphics2D) mask.createGraphics();
+
+ g2.setColor(Color.white);
+ g2.fillRect(0, 0, maskWidth, maskHeight);
+
+ g2.dispose();
+
+ ShadowRenderer shadowRenderer = new ShadowRenderer(size, opacity, SHADOW_COLOR);
+ BufferedImage dropShadow = shadowRenderer.createShadow(mask);
+
+ BufferedImage render = new BufferedImage(maskWidth * 2, maskHeight * 2, BufferedImage.TYPE_INT_ARGB);
+ g2 = (Graphics2D)render.createGraphics();
+
+ g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ Rectangle2D.Float clip = new Rectangle2D.Float(sampleX, sampleY, sampleWidth, sampleHeight);
+
+ g2.setColor(Color.white);
+ g2.fill(clip);
+
+ g2.drawImage(dropShadow, 0, 0, null);
+
+ g2.dispose();
+
+ return render.getSubimage(sampleX, sampleY, sampleWidth, sampleHeight);
}
/**
@@ -112,15 +397,15 @@
public float getStartAngle(String code)
{
if (TOP_LEFT.equalsIgnoreCase(code))
- return 90f;
+ return ANGLE_TOP_LEFT;
if (TOP_RIGHT.equalsIgnoreCase(code))
- return 0f;
+ return ANGLE_TOP_RIGHT;
if (BOTTOM_LEFT.equalsIgnoreCase(code))
- return 180f;
+ return ANGLE_BOTTOM_LEFT;
if (BOTTOM_RIGHT.equalsIgnoreCase(code))
- return 270f;
+ return ANGLE_BOTTOM_RIGHT;
- return 0f;
+ return ANGLE_TOP_RIGHT;
}
/**
Modified: tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/RoundedCornerService.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/RoundedCornerService.java?view=diff&rev=531707&r1=531706&r2=531707
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/RoundedCornerService.java (original)
+++ tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/RoundedCornerService.java Mon Apr 23 20:08:25 2007
@@ -11,7 +11,10 @@
import org.apache.tapestry.web.WebRequest;
import org.apache.tapestry.web.WebResponse;
+import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
@@ -31,6 +34,14 @@
public static final String PARM_HEIGHT = "h";
public static final String PARM_ANGLE = "a";
+ public static final String PARM_SHADOW_WIDTH ="sw";
+ public static final String PARM_SHADOW_OPACITY ="o";
+ public static final String PARM_SHADOW_SIDE = "s";
+
+ public static final String PARM_WHOLE_SHADOW = "shadow";
+ public static final String PARM_ARC_HEIGHT = "ah";
+ public static final String PARM_ARC_WIDTH = "aw";
+
private static final long MONTH_SECONDS = 60 * 60 * 24 * 30;
private static final long EXPIRES = System.currentTimeMillis() + 365 * 24 * 60 * 60 * 1000L;
@@ -44,7 +55,10 @@
private WebResponse _response;
private RoundedCornerGenerator _generator = new RoundedCornerGenerator();
-
+
+ // holds pre-built binaries for previously generated colors
+ private Map _imageCache = new HashMap();
+
public ILink getLink(boolean post, Object parameter)
{
Defense.notNull(parameter, "parameter");
@@ -62,31 +76,63 @@
public void service(IRequestCycle cycle)
throws IOException
{
+ if (_request.getHeader("If-Modified-Since") != null)
+ {
+ _response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ return;
+ }
+
String color = cycle.getParameter(PARM_COLOR);
String bgColor = cycle.getParameter(PARM_BACKGROUND_COLOR);
int width = getIntParam(cycle.getParameter(PARM_WIDTH));
int height = getIntParam(cycle.getParameter(PARM_HEIGHT));
String angle = cycle.getParameter(PARM_ANGLE);
+
+ int shadowWidth = getIntParam(cycle.getParameter(PARM_SHADOW_WIDTH));
+ float shadowOpacity = getFloatParam(cycle.getParameter(PARM_SHADOW_OPACITY));
+ String side = cycle.getParameter(PARM_SHADOW_SIDE);
- OutputStream os = null;
+ boolean wholeShadow = Boolean.valueOf(cycle.getParameter(PARM_WHOLE_SHADOW)).booleanValue();
+ float arcWidth = getFloatParam(cycle.getParameter(PARM_ARC_WIDTH));
+ float arcHeight = getFloatParam(cycle.getParameter(PARM_ARC_HEIGHT));
+ String hashKey = color + bgColor + width + height + angle + shadowWidth + shadowOpacity + side + wholeShadow;
+
+ ByteArrayOutputStream bo = null;
+
try {
+
+ String type = (bgColor != null) ? "gif" : "png";
- if (_request.getHeader("If-Modified-Since") != null)
- {
- _response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
+ byte[] data = (byte[])_imageCache.get(hashKey);
+ if (data != null) {
+
+ writeImageResponse(data, type);
return;
}
- byte[] data = _generator.buildCorner(color, bgColor, width, height, angle);
+ BufferedImage image = null;
- _response.setDateHeader("Expires", EXPIRES);
- _response.setHeader("Cache-Control", "public, max-age=" + (MONTH_SECONDS * 3));
- _response.setContentLength(data.length);
-
- os = _response.getOutputStream(new ContentType("image/gif"));
+ if (wholeShadow) {
- os.write(data);
+ image = _generator.buildShadow(bgColor, width, height, arcWidth, arcHeight, shadowWidth, shadowOpacity);
+ } else if (side != null) {
+
+ image = _generator.buildSideShadow(side, shadowWidth, shadowOpacity);
+ } else {
+
+ image = _generator.buildCorner(color, bgColor, width, height, angle, shadowWidth, shadowOpacity);
+ }
+
+ bo = new ByteArrayOutputStream();
+
+ ImageIO.write(image, type, bo);
+
+ data = bo.toByteArray();
+
+ _imageCache.put(hashKey, data);
+
+ writeImageResponse(data, type);
} catch (Throwable ex) {
@@ -94,6 +140,32 @@
_exceptionReporter.reportRequestException("Error creating image.", ex);
} finally {
try {
+ if (bo != null) {
+ bo.close();
+ }
+ } catch (Throwable t) {
+ // ignore
+ }
+
+ }
+ }
+
+ void writeImageResponse(byte[] data, String type)
+ throws Exception
+ {
+ OutputStream os = null;
+
+ try {
+ _response.setDateHeader("Expires", EXPIRES);
+ _response.setHeader("Cache-Control", "public, max-age=" + (MONTH_SECONDS * 3));
+ _response.setContentLength(data.length);
+
+ os = _response.getOutputStream(new ContentType("image/" + type));
+
+ os.write(data);
+
+ } finally {
+ try {
if (os != null) {
os.flush();
os.close();
@@ -101,7 +173,6 @@
} catch (Throwable t) {
// ignore
}
-
}
}
@@ -111,6 +182,14 @@
return 0;
return Integer.valueOf(value).intValue();
+ }
+
+ private float getFloatParam(String value)
+ {
+ if (value == null)
+ return 0f;
+
+ return Float.valueOf(value).floatValue();
}
public String getName()
Added: tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/ShadowRenderer.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/ShadowRenderer.java?view=auto&rev=531707
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/ShadowRenderer.java (added)
+++ tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/ShadowRenderer.java Mon Apr 23 20:08:25 2007
@@ -0,0 +1,357 @@
+package org.apache.tapestry.contrib.services.impl;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.awt.image.Raster;
+import java.awt.image.WritableRaster;
+
+/**
+ *
+ */
+public class ShadowRenderer {
+
+ // size of the shadow in pixels (defines the fuzziness)
+ private int size = 5;
+
+ // opacity of the shadow
+ private float opacity = 0.5f;
+
+ // color of the shadow
+ private Color color = Color.BLACK;
+
+ /**
+ * <p>A shadow renderer needs three properties to generate shadows.
+ * These properties are:</p>
+ * <ul>
+ * <li><i>size</i>: The size, in pixels, of the shadow. This property also
+ * defines the fuzzyness.</li>
+ * <li><i>opacity</i>: The opacity, between 0.0 and 1.0, of the shadow.</li>
+ * <li><i>color</i>: The color of the shadow. Shadows are not meant to be
+ * black only.</li>
+ * </ul>
+ * @param size the size of the shadow in pixels. Defines the fuzziness.
+ * @param opacity the opacity of the shadow.
+ * @param color the color of the shadow.
+ */
+ public ShadowRenderer(final int size, final float opacity, final Color color) {
+
+ setSize(size);
+ setOpacity(opacity);
+ setColor(color);
+ }
+
+ /**
+ * <p>Gets the color used by the renderer to generate shadows.</p>
+ * @return this renderer's shadow color
+ */
+ public Color getColor() {
+ return color;
+ }
+
+ /**
+ * <p>Sets the color used by the renderer to generate shadows.</p>
+ * <p>Consecutive calls to {@link #createShadow} will all use this color
+ * until it is set again.</p>
+ * <p>If the color provided is null, the previous color will be retained.</p>
+ * @param shadowColor the generated shadows color
+ */
+ public void setColor(final Color shadowColor) {
+ if (shadowColor != null) {
+ Color oldColor = this.color;
+ this.color = shadowColor;
+ }
+ }
+
+ /**
+ * <p>Gets the opacity used by the renderer to generate shadows.</p>
+ * <p>The opacity is comprised between 0.0f and 1.0f; 0.0f being fully
+ * transparent and 1.0f fully opaque.</p>
+ * @return this renderer's shadow opacity
+ */
+ public float getOpacity() {
+ return opacity;
+ }
+
+ /**
+ * <p>Sets the opacity used by the renderer to generate shadows.</p>
+ * <p>Consecutive calls to {@link #createShadow} will all use this opacity
+ * until it is set again.</p>
+ * <p>The opacity is comprised between 0.0f and 1.0f; 0.0f being fully
+ * transparent and 1.0f fully opaque. If you provide a value out of these
+ * boundaries, it will be restrained to the closest boundary.</p>
+ * @param shadowOpacity the generated shadows opacity
+ */
+ public void setOpacity(final float shadowOpacity) {
+ float oldOpacity = this.opacity;
+
+ if (shadowOpacity < 0.0) {
+ this.opacity = 0.0f;
+ } else if (shadowOpacity > 1.0f) {
+ this.opacity = 1.0f;
+ } else {
+ this.opacity = shadowOpacity;
+ }
+ }
+
+ /**
+ * <p>Gets the size in pixel used by the renderer to generate shadows.</p>
+ * @return this renderer's shadow size
+ */
+ public int getSize() {
+ return size;
+ }
+
+ /**
+ * <p>Sets the size, in pixels, used by the renderer to generate shadows.</p>
+ * <p>The size defines the blur radius applied to the shadow to create the
+ * fuzziness.</p>
+ * <p>There is virtually no limit to the size. The size cannot be negative.
+ * If you provide a negative value, the size will be 0 instead.</p>
+ * @param shadowSize the generated shadows size in pixels (fuzziness)
+ */
+ public void setSize(final int shadowSize) {
+ int oldSize = this.size;
+
+ if (shadowSize < 0) {
+ this.size = 0;
+ } else {
+ this.size = shadowSize;
+ }
+ }
+
+ /**
+ * <p>Generates the shadow for a given picture and the current properties
+ * of the renderer.</p>
+ * <p>The generated image dimensions are computed as following:</p>
+ * <pre>
+ * width = imageWidth + 2 * shadowSize
+ * height = imageHeight + 2 * shadowSize
+ * </pre>
+ * @param image the picture from which the shadow must be cast
+ * @return the picture containing the shadow of <code>image</code>
+ */
+ public BufferedImage createShadow(final BufferedImage image) {
+
+ // Written by Sesbastien Petrucci
+ int shadowSize = size * 2;
+
+ int srcWidth = image.getWidth();
+ int srcHeight = image.getHeight();
+
+ int dstWidth = srcWidth + shadowSize;
+ int dstHeight = srcHeight + shadowSize;
+
+ int left = size;
+ int right = shadowSize - left;
+
+ int yStop = dstHeight - right;
+
+ int shadowRgb = color.getRGB() & 0x00FFFFFF;
+ int[] aHistory = new int[shadowSize];
+ int historyIdx;
+
+ int aSum;
+
+ BufferedImage dst = new BufferedImage(dstWidth, dstHeight,
+ BufferedImage.TYPE_INT_ARGB);
+
+ int[] dstBuffer = new int[dstWidth * dstHeight];
+ int[] srcBuffer = new int[srcWidth * srcHeight];
+
+ getPixels(image, 0, 0, srcWidth, srcHeight, srcBuffer);
+
+ int lastPixelOffset = right * dstWidth;
+ float hSumDivider = 1.0f / shadowSize;
+ float vSumDivider = opacity / shadowSize;
+
+ int[] hSumLookup = new int[256 * shadowSize];
+ for (int i = 0; i < hSumLookup.length; i++) {
+ hSumLookup[i] = (int) (i * hSumDivider);
+ }
+
+ int[] vSumLookup = new int[256 * shadowSize];
+ for (int i = 0; i < vSumLookup.length; i++) {
+ vSumLookup[i] = (int) (i * vSumDivider);
+ }
+
+ int srcOffset;
+
+ // horizontal pass : extract the alpha mask from the source picture and
+ // blur it into the destination picture
+ for (int srcY = 0, dstOffset = left * dstWidth; srcY < srcHeight; srcY++) {
+
+ // first pixels are empty
+ for (historyIdx = 0; historyIdx < shadowSize; ) {
+ aHistory[historyIdx++] = 0;
+ }
+
+ aSum = 0;
+ historyIdx = 0;
+ srcOffset = srcY * srcWidth;
+
+ // compute the blur average with pixels from the source image
+ for (int srcX = 0; srcX < srcWidth; srcX++) {
+
+ int a = hSumLookup[aSum];
+ dstBuffer[dstOffset++] = a << 24; // store the alpha value only
+ // the shadow color will be added in the next pass
+
+ aSum -= aHistory[historyIdx]; // substract the oldest pixel from the sum
+
+ // extract the new pixel ...
+ a = srcBuffer[srcOffset + srcX] >>> 24;
+ aHistory[historyIdx] = a; // ... and store its value into history
+ aSum += a; // ... and add its value to the sum
+
+ if (++historyIdx >= shadowSize) {
+ historyIdx -= shadowSize;
+ }
+ }
+
+ // blur the end of the row - no new pixels to grab
+ for (int i = 0; i < shadowSize; i++) {
+
+ int a = hSumLookup[aSum];
+ dstBuffer[dstOffset++] = a << 24;
+
+ // substract the oldest pixel from the sum ... and nothing new to add !
+ aSum -= aHistory[historyIdx];
+
+ if (++historyIdx >= shadowSize) {
+ historyIdx -= shadowSize;
+ }
+ }
+ }
+
+ // vertical pass
+ for (int x = 0, bufferOffset = 0; x < dstWidth; x++, bufferOffset = x) {
+
+ aSum = 0;
+
+ // first pixels are empty
+ for (historyIdx = 0; historyIdx < left;) {
+ aHistory[historyIdx++] = 0;
+ }
+
+ // and then they come from the dstBuffer
+ for (int y = 0; y < right; y++, bufferOffset += dstWidth) {
+ int a = dstBuffer[bufferOffset] >>> 24; // extract alpha
+ aHistory[historyIdx++] = a; // store into history
+ aSum += a; // and add to sum
+ }
+
+ bufferOffset = x;
+ historyIdx = 0;
+
+ // compute the blur avera`ge with pixels from the previous pass
+ for (int y = 0; y < yStop; y++, bufferOffset += dstWidth) {
+
+ int a = vSumLookup[aSum];
+ dstBuffer[bufferOffset] = a << 24 | shadowRgb; // store alpha value + shadow color
+
+ aSum -= aHistory[historyIdx]; // substract the oldest pixel from the sum
+
+ a = dstBuffer[bufferOffset + lastPixelOffset] >>> 24; // extract the new pixel ...
+ aHistory[historyIdx] = a; // ... and store its value into history
+ aSum += a; // ... and add its value to the sum
+
+ if (++historyIdx >= shadowSize) {
+ historyIdx -= shadowSize;
+ }
+ }
+
+ // blur the end of the column - no pixels to grab anymore
+ for (int y = yStop; y < dstHeight; y++, bufferOffset += dstWidth) {
+
+ int a = vSumLookup[aSum];
+ dstBuffer[bufferOffset] = a << 24 | shadowRgb;
+
+ aSum -= aHistory[historyIdx]; // substract the oldest pixel from the sum
+
+ if (++historyIdx >= shadowSize) {
+ historyIdx -= shadowSize;
+ }
+ }
+ }
+
+ setPixels(dst, 0, 0, dstWidth, dstHeight, dstBuffer);
+ return dst;
+ }
+
+ /**
+ * <p>Returns an array of pixels, stored as integers, from a
+ * <code>BufferedImage</code>. The pixels are grabbed from a rectangular
+ * area defined by a location and two dimensions. Calling this method on
+ * an image of type different from <code>BufferedImage.TYPE_INT_ARGB</code>
+ * and <code>BufferedImage.TYPE_INT_RGB</code> will unmanage the image.</p>
+ *
+ * @param img the source image
+ * @param x the x location at which to start grabbing pixels
+ * @param y the y location at which to start grabbing pixels
+ * @param w the width of the rectangle of pixels to grab
+ * @param h the height of the rectangle of pixels to grab
+ * @param pixels a pre-allocated array of pixels of size w*h; can be null
+ * @return <code>pixels</code> if non-null, a new array of integers
+ * otherwise
+ * @throws IllegalArgumentException is <code>pixels</code> is non-null and
+ * of length < w*h
+ */
+ public static int[] getPixels(BufferedImage img,
+ int x, int y, int w, int h, int[] pixels) {
+ if (w == 0 || h == 0) {
+ return new int[0];
+ }
+
+ if (pixels == null) {
+ pixels = new int[w * h];
+ } else if (pixels.length < w * h) {
+ throw new IllegalArgumentException("pixels array must have a length" +
+ " >= w*h");
+ }
+
+ int imageType = img.getType();
+ if (imageType == BufferedImage.TYPE_INT_ARGB ||
+ imageType == BufferedImage.TYPE_INT_RGB) {
+ Raster raster = img.getRaster();
+ return (int[]) raster.getDataElements(x, y, w, h, pixels);
+ }
+
+ // Unmanages the image
+ return img.getRGB(x, y, w, h, pixels, 0, w);
+ }
+
+ /**
+ * <p>Writes a rectangular area of pixels in the destination
+ * <code>BufferedImage</code>. Calling this method on
+ * an image of type different from <code>BufferedImage.TYPE_INT_ARGB</code>
+ * and <code>BufferedImage.TYPE_INT_RGB</code> will unmanage the image.</p>
+ *
+ * @param img the destination image
+ * @param x the x location at which to start storing pixels
+ * @param y the y location at which to start storing pixels
+ * @param w the width of the rectangle of pixels to store
+ * @param h the height of the rectangle of pixels to store
+ * @param pixels an array of pixels, stored as integers
+ * @throws IllegalArgumentException is <code>pixels</code> is non-null and
+ * of length < w*h
+ */
+ public static void setPixels(BufferedImage img,
+ int x, int y, int w, int h, int[] pixels) {
+ if (pixels == null || w == 0 || h == 0) {
+ return;
+ } else if (pixels.length < w * h) {
+ throw new IllegalArgumentException("pixels array must have a length" +
+ " >= w*h");
+ }
+
+ int imageType = img.getType();
+ if (imageType == BufferedImage.TYPE_INT_ARGB ||
+ imageType == BufferedImage.TYPE_INT_RGB) {
+ WritableRaster raster = img.getRaster();
+ raster.setDataElements(x, y, w, h, pixels);
+ } else {
+ // Unmanages the image
+ img.setRGB(x, y, w, h, pixels, 0, w);
+ }
+ }
+}
Propchange: tapestry/tapestry4/trunk/tapestry-contrib/src/java/org/apache/tapestry/contrib/services/impl/ShadowRenderer.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tapestry/tapestry4/trunk/tapestry-contrib/src/test/org/apache/tapestry/contrib/services/TestRoundedCornerService.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-contrib/src/test/org/apache/tapestry/contrib/services/TestRoundedCornerService.java?view=diff&rev=531707&r1=531706&r2=531707
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-contrib/src/test/org/apache/tapestry/contrib/services/TestRoundedCornerService.java (original)
+++ tapestry/tapestry4/trunk/tapestry-contrib/src/test/org/apache/tapestry/contrib/services/TestRoundedCornerService.java Mon Apr 23 20:08:25 2007
@@ -4,31 +4,22 @@
import org.apache.tapestry.contrib.services.impl.RoundedCornerGenerator;
import org.testng.annotations.Test;
+import java.awt.image.BufferedImage;
+
/**
* Tests functionality of {@link org.apache.tapestry.contrib.services.impl.RoundedCornerService}.
*/
@Test
public class TestRoundedCornerService extends TestBase {
- public void test_Build_Corner()
- throws Exception
- {
- RoundedCornerGenerator generator = new RoundedCornerGenerator();
- byte[] data = generator.buildCorner("FF7E00", null, 30, 30, "tr");
-
- assert data != null;
- assert data.length > 0;
- }
-
- public void test_Corner_Cached()
+ public void test_Build_Corner()
throws Exception
{
RoundedCornerGenerator generator = new RoundedCornerGenerator();
- byte[] data1 = generator.buildCorner("FF7E00", null, 30, 30, "tr");
- byte[] data2 = generator.buildCorner("FF7E00", null, 30, 30, "tr");
-
- assert data1 == data2;
+ BufferedImage image = generator.buildCorner("FF7E00", null, 30, 30, "tr", -1, -1);
+ assert image.getWidth() == 30;
+ assert image.getHeight() == 30;
}
}
Modified: tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/pom.xml
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/pom.xml?view=diff&rev=531707&r1=531706&r2=531707
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/pom.xml (original)
+++ tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/pom.xml Mon Apr 23 20:08:25 2007
@@ -108,6 +108,13 @@
<include>*.properties</include>
</includes>
</resource>
+ <resource>
+ <directory>src/java</directory>
+ <includes>
+ <include>**/*.page</include>
+ <include>**/*.jwc</include>
+ </includes>
+ </resource>
</resources>
<plugins>
Modified: tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/LocaleList.html
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/LocaleList.html?view=diff&rev=531707&r1=531706&r2=531707
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/LocaleList.html (original)
+++ tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/LocaleList.html Mon Apr 23 20:08:25 2007
@@ -1,22 +1,20 @@
<span jwcid="@Border">
<p>
-Simple For loop listing locales.
+Simple <code>For</code> loop listing locales.
</p>
<style>
- .localeList {
- /* padding:0.3em; */
+
+ .localeList {
background: #2A78B0;
display:block;
float:left;
- width:20%;
+ width:20%;
margin-top:0.6em;
margin-left:0.5em;
}
-
.localeList a { color: #fff;}
-
.localeList p { margin: 0 10px;}
.roundtop {
@@ -40,38 +38,28 @@
display: block !important;
}
- .selected {
- background: #efefef;
- }
-
- .selected a {
- color: #000;
- }
+ .selected { background: #efefef; }
+ .selected a { color: #000; }
.detail {
- clear:left;
- display:block;
- padding: 1em;
- width: 56%;
- margin-top:1em;
- border-left: 1px solid #efefef;
- border-top: 1px solid #efefef;
- border-bottom: 1px solid #aaa;
- border-right: 1px solid #aaa;
- -moz-border-radius: 0.7em;
- }
-
- .status {
+ display:block;
+ margin-top:2em;
+ padding: 0 1.1em 2em;
+ background: url("rounded?bc=white&w=600&h=40&shadow=true&ah=10&aw=10&sw=4&o=.5") left bottom no-repeat;
+ }
+
+ .status {
display:block;
clear:both;
- width:70%;
- height: 50px;
+ width:80%;
+ height: 4em;
overflow:auto;
font-family: arial;
font-size:8pt;
padding: 0.4em;
border:1px dotted #D6AE33;
- }
+ margin-top:1em;
+ }
.clear {
clear:both;
@@ -80,45 +68,37 @@
width:100%;
height: 20px;
}
-
</style>
-<span jwcid="localeDetail@Any">
- <p class="detail" jwcid="@If" condition="ognl:selected" >
- <strong>Country:</strong>
- <span jwcid="@Insert" value="ognl:selected.displayCountry" mode="ognl:@org.apache.tapestry.components.InsertMode@BREAK" />
-
- <strong>Language:</strong>
- <span jwcid="@Insert" value="ognl:selected.displayLanguage" mode="ognl:@org.apache.tapestry.components.InsertMode@BREAK" />
-
- <strong>Variant:</strong>
- <span jwcid="@Insert" value="ognl:selected.displayVariant" mode="ognl:@org.apache.tapestry.components.InsertMode@BREAK" />
- </p>
-</span>
+<div jwcid="localeDetail@Any">
+ <p class="detail" jwcid="@If" condition="ognl:selected" >
+ <strong>Country:</strong>
+ <span jwcid="@Insert" value="ognl:selected.displayCountry" mode="ognl:@org.apache.tapestry.components.InsertMode@BREAK" />
+
+ <strong>Language:</strong>
+ <span jwcid="@Insert" value="ognl:selected.displayLanguage" mode="ognl:@org.apache.tapestry.components.InsertMode@BREAK" />
+
+ <strong>Variant:</strong>
+ <span jwcid="@Insert" value="ognl:selected.displayVariant" mode="ognl:@org.apache.tapestry.components.InsertMode@BREAK" />
+ </p>
+</div>
<div jwcid="status@Any" class="status" >
- <span jwcid="@Insert" value="ognl:status" />
+ <span jwcid="@Insert" value="ognl:status" />
</div>
+
<div class="ognl:currentSelected ? 'selected localeList' : 'localeList'"
jwcid="localeList@For"
source="ognl:@org.apache.tapestry.timetracker.page.LocaleList@LOCALES" value="ognl:currLocale">
- <div jwcid="@Any" class="ognl:currentSelected ? 'selectedRoundtop' : 'roundtop'">
-
- <img jwcid="@Any" src="ognl:getRoundedUrl('tl')" width="8" height="8" class="corner" style="display: none" />
-
- </div>
- <p>
- <a jwcid="localeLink@DirectLink" listener="listener:selectLocale" parameters="ognl:{currLocale.language, currLocale.country, currLocale.variant}"
- updateComponents="ognl:{'localeDetail',page.components.localeList.clientId}" stateful="ognl:false">
- <span jwcid="@Insert" value="ognl:currLocale.toString()" />
- </a>
- </p>
- <div jwcid="@Any" class="ognl:currentSelected ? 'selectedRoundbottom' : 'roundbottom'">
-
- <img jwcid="@Any" src="ognl:getRoundedUrl('bl')" width="8" height="8" class="corner" style="display: none" />
-
+ <div jwcid="@Locale" selected="ognl:currentSelected">
+ <p>
+ <a jwcid="localeLink@DirectLink" listener="listener:selectLocale" parameters="ognl:{currLocale.language, currLocale.country, currLocale.variant}"
+ updateComponents="ognl:{'localeDetail',page.components.localeList.clientId}" stateful="ognl:false">
+ <span jwcid="@Insert" value="ognl:currLocale.toString()" />
+ </a>
+ </p>
</div>
</div>
Modified: tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/WEB-INF/timetracker.application
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/WEB-INF/timetracker.application?view=diff&rev=531707&r1=531706&r2=531707
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/WEB-INF/timetracker.application (original)
+++ tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/context/WEB-INF/timetracker.application Mon Apr 23 20:08:25 2007
@@ -15,15 +15,17 @@
limitations under the License.
-->
-<!DOCTYPE application PUBLIC
- "-//Apache Software Foundation//Tapestry Specification 4.0//EN"
- "http://tapestry.apache.org/dtd/Tapestry_4_0.dtd">
-
+<!DOCTYPE application PUBLIC
+ "-//Apache Software Foundation//Tapestry Specification 4.0//EN"
+ "http://tapestry.apache.org/dtd/Tapestry_4_0.dtd">
+
<application name="Tapestry TimeTracker">
-
- <meta key="org.apache.tapestry.namespace-properties-name" value="messages" />
- <meta key="org.apache.tapestry.page-class-packages" value="org.apache.tapestry.timetracker.page"/>
-
- <library id="contrib" specification-path="classpath:/org/apache/tapestry/contrib/Contrib.library"/>
-
+
+ <meta key="org.apache.tapestry.namespace-properties-name" value="messages" />
+ <meta key="org.apache.tapestry.page-class-packages" value="org.apache.tapestry.timetracker.page"/>
+
+ <library id="contrib" specification-path="classpath:/org/apache/tapestry/contrib/Contrib.library"/>
+
+ <component-type type="Locale" specification-path="classpath:/org/apache/tapestry/timetracker/component/Locale.jwc" />
+
</application>
Added: tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/Locale.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/Locale.java?view=auto&rev=531707
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/Locale.java (added)
+++ tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/Locale.java Mon Apr 23 20:08:25 2007
@@ -0,0 +1,48 @@
+package org.apache.tapestry.timetracker.component;
+
+import org.apache.tapestry.AbstractComponent;
+import org.apache.tapestry.IMarkupWriter;
+import org.apache.tapestry.IRequestCycle;
+import org.apache.tapestry.annotations.Parameter;
+
+/**
+ *
+ */
+public abstract class Locale extends AbstractComponent {
+
+ @Parameter(required = true)
+ public abstract boolean isSelected();
+
+ public void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
+ {
+ boolean selected = isSelected();
+
+ renderRow(writer, "selectedRoundtop", "roundtop", "tl", selected);
+
+ super.renderBody(writer, cycle);
+
+ renderRow(writer, "selectedRoundbottom", "roundbottom", "bl", selected);
+ }
+
+ void renderRow(IMarkupWriter writer, String selectedCssClass, String cssClass, String anchor, boolean selected)
+ {
+ writer.begin("div");
+ writer.attribute("class", selected ? selectedCssClass :cssClass);
+
+ writer.beginEmpty("img");
+ writer.attribute("src", getRoundedUrl(anchor, selected));
+ writer.attribute("width", "8");
+ writer.attribute("height", "8");
+ writer.attribute("class", "corner");
+ writer.attribute("style", "display:none");
+
+ writer.end("div");
+ }
+
+ String getRoundedUrl(String anchor, boolean selected)
+ {
+ return "rounded?c=" +
+ (selected ? "efefef" : "2A78B0")
+ + "&bc=white&w=8&h=8&a=" + anchor;
+ }
+}
Propchange: tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/Locale.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/Locale.jwc
URL: http://svn.apache.org/viewvc/tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/Locale.jwc?view=auto&rev=531707
==============================================================================
--- tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/Locale.jwc (added)
+++ tapestry/tapestry4/trunk/tapestry-examples/TimeTracker/src/java/org/apache/tapestry/timetracker/component/Locale.jwc Mon Apr 23 20:08:25 2007
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2004, 2005 The Apache Software Foundation
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<!DOCTYPE component-specification PUBLIC
+ "-//Apache Software Foundation//Tapestry Specification 4.0//EN"
+ "http://tapestry.apache.org/dtd/Tapestry_4_0.dtd">
+
+<component-specification class="org.apache.tapestry.timetracker.component.Locale">
+</component-specification>