001: package com.xoetrope.swing;
002:
003: import java.awt.AlphaComposite;
004: import java.awt.Color;
005: import java.awt.Dimension;
006: import java.awt.GradientPaint;
007: import java.awt.Graphics;
008: import java.awt.Graphics2D;
009: import java.awt.Insets;
010: import java.awt.Shape;
011: import java.awt.geom.AffineTransform;
012: import java.awt.geom.Area;
013: import java.awt.geom.Rectangle2D;
014: import java.awt.geom.RoundRectangle2D;
015: import java.awt.image.BufferedImage;
016: import net.xoetrope.swing.XImage;
017:
018: /**
019: * Display an image along with a reflection of that image at a user defined angle.
020: * The image is render at a size that preserves the aspect ration but allows
021: * enough room to just show both the image and its reflection
022: *
023: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
024: * the GNU Public License (GPL), please see license.txt for more details. If
025: * you make commercial use of this software you must purchase a commercial
026: * license from Xoetrope.</p>
027: * <p> $Revision: 1.2 $</p>
028: */
029: public class XReflectedImage extends XImage {
030: /** The shear factor, defaults to -0.15 */
031: protected double shear = -0.15;
032:
033: /**
034: * Creates a new instance of XReflectedImage
035: */
036: public XReflectedImage() {
037: }
038:
039: /**
040: * Sets the degree of shear of the control's text.
041: * The range is 0 to 3600.
042: * @param value the new shear factor
043: */
044: public void setShear(double value) {
045: shear = value;
046: repaint();
047: }
048:
049: /**
050: * Sets the amount of arc used on the border of
051: * the component.
052: * @param value the new arc amount
053: */
054: public void setArc(int value) {
055: arc = value;
056: repaint();
057: }
058:
059: /**
060: * Gets the amount of arc used on the border of
061: * the component.
062: * @return the arc amount
063: */
064: public int getArc() {
065: return arc;
066: }
067:
068: /**
069: * Gets the degree of shear of the control's text.
070: * The range is 0 to 3600.
071: * @return the new shear factor
072: */
073: public double getShear() {
074: return shear;
075: }
076:
077: /**
078: * Render the component
079: * @param g the graphics context
080: */
081: public void paintComponent(Graphics g) {
082: if (image != null) {
083: // fill the background with a texture ...
084: Graphics2D g2d = (Graphics2D) g;
085:
086: Dimension size = getSize();
087:
088: int avatarWidth = image.getWidth(this );
089: int avatarHeight = image.getHeight(this );
090: if (avatarWidth <= 0) {
091: avatarWidth = size.width;
092: avatarHeight = size.height;
093: }
094:
095: // Do that in the constructor ...
096: BufferedImage reflection = new BufferedImage(avatarWidth,
097: avatarHeight, BufferedImage.TYPE_INT_ARGB);
098: Graphics2D reflectionGraphics = reflection.createGraphics();
099:
100: AffineTransform tranform = AffineTransform
101: .getScaleInstance(1.0, -1.0);
102: tranform.shear(shear, 0);
103: tranform.translate(0, -avatarHeight);
104:
105: // Draw the flipped image
106: reflectionGraphics.drawImage(image, tranform, this );
107:
108: GradientPaint painter = new GradientPaint(0.0F, 0.0F,
109: new Color(0.0F, 0.0F, 0.0F, 0.5F), 0.0F,
110: avatarHeight / 2.0F, new Color(0.0F, 0.0F, 0.0F,
111: 1.0F));
112:
113: // This use : Ar = Ad*(1-As) and Cr = Cd*(1-As)
114: reflectionGraphics.setComposite(AlphaComposite.DstOut);
115: reflectionGraphics.setPaint(painter);
116: // This will make our image transluent ...
117: reflectionGraphics.fill(new Rectangle2D.Double(0, 0,
118: avatarWidth, avatarHeight));
119:
120: reflectionGraphics.dispose();
121:
122: double scale = Math.min(
123: (1.0 * size.height / (1.6 * avatarHeight)),
124: (1.0 * size.width / (1.1 * avatarWidth)));
125: g2d.drawImage(image, 0, 0, (int) (scale * avatarWidth),
126: (int) (scale * avatarHeight), this );
127: // Using the default composite method, this will merge the reflection with the background
128: g2d.drawImage(reflection, 0, (int) (scale * avatarHeight),
129: (int) (scale * avatarWidth),
130: (int) (scale * avatarHeight), this );
131:
132: if (drawBorder) {
133: // Draw the border
134: Dimension componentSize = getSize();
135: Shape borderShape = null;
136: Insets insets = new Insets(0, 0, 0, 0);
137: Shape clipShape = g2d.getClip();
138: borderShape = new RoundRectangle2D.Double(insets.left,
139: insets.top, componentSize.width - 1
140: - insets.left - insets.right,
141: componentSize.height - 1 - insets.top
142: - insets.bottom, arc, arc);
143: g2d.setColor(getForeground());
144: g2d.draw(borderShape);
145: Area clipArea = new Area(borderShape);
146: clipArea.intersect(new Area(clipShape));
147:
148: // Clip any subsequent images
149: g2d.setClip(clipArea);
150: }
151: }
152: }
153:
154: /**
155: * Set one or more attributes of the component.
156: * <OL>
157: * <LI>content, value=the image file name</LI>
158: * <LI>imagename, value=the image file name</LI>
159: * <LI>tooltip, value=the tooltip text</LI>
160: * <LI>hear, value=the percentage of shear for the reflection</LI>
161: * </OL>
162: * @param attribName the attribute name
163: * @param attribValue the attribute value
164: * @return 0 for success, non zero otherwise
165: */
166: public int setAttribute(String attribName, Object attribValue) {
167: String attribValueStr = (String) attribValue;
168: String attribNameLwr = attribName.toLowerCase();
169: if (attribNameLwr.equals("shear"))
170: shear = Double.parseDouble(attribValueStr);
171: else if (attribNameLwr.equals("border"))
172: drawBorder = attribValueStr.equals("true")
173: || attribValueStr.equals("1");
174: else if (attribNameLwr.equals("arc"))
175: arc = Math.max(0, new Integer(attribValueStr).intValue());
176:
177: else
178: super .setAttribute(attribName, attribValue);
179:
180: return 0;
181: }
182: }
|