001: package com.xoetrope.swing;
002:
003: import com.xoetrope.swing.util.XShapeGenerator;
004: import java.awt.Dimension;
005: import java.awt.Graphics;
006: import java.awt.Graphics2D;
007: import java.awt.Rectangle;
008: import java.awt.Shape;
009: import java.awt.TexturePaint;
010: import java.awt.geom.Ellipse2D;
011: import java.awt.geom.GeneralPath;
012: import java.awt.geom.Rectangle2D;
013: import java.awt.image.BufferedImage;
014: import javax.swing.JComponent;
015:
016: import net.xoetrope.xui.XAttributedComponent;
017:
018: /**
019: * Draws a simple shape
020: *
021: * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
022: * the GNU Public License (GPL), please see license.txt for more details. If
023: * you make commercial use of this software you must purchase a commercial
024: * license from Xoetrope.</p>
025: * <p> $Revision: 1.12 $</p>
026: */
027: public class XShape extends JComponent implements XAttributedComponent,
028: XShapeGenerator {
029: private BufferedImage backgroundImage;
030:
031: /**
032: * the drawing / shape mode
033: */
034: protected int mode = 0;
035:
036: /**
037: * A rectangle shape
038: */
039: public static final int RECTANGLE = 0;
040:
041: /**
042: * A vertical or horizontal line
043: */
044: public static final int ORTHO_LINE = 1;
045:
046: /**
047: * An extra bold horizontal line
048: */
049: public static final int EXTRABOLD_HORIZONTAL = 2;
050:
051: /**
052: * A bold horizontal line
053: */
054: public static final int BOLD_HORIZONTAL = 3;
055:
056: /**
057: * A vertical line
058: */
059: public static final int NORMAL_HORIZONTAL = 4;
060:
061: /**
062: * A thin horizontal line
063: */
064: public static final int THIN_HORIZONTAL = 5;
065:
066: /**
067: * An extra bold vertical line
068: */
069: public static final int EXTRABOLD_VERTICAL = 6;
070:
071: /**
072: * A bold vertical line
073: */
074: public static final int BOLD_VERTICAL = 7;
075:
076: /**
077: * A vertical line
078: */
079: public static final int NORMAL_VERTICAL = 8;
080:
081: /**
082: * A thin vertical line
083: */
084: public static final int THIN_VERTICAL = 9;
085:
086: /**
087: * A line from the top right to the bottom left
088: */
089: public static final int RIGHT_TOP_LINE = 10;
090:
091: /**
092: * A line from the top left to the bottom right
093: */
094: public static final int LEFT_TOP_LINE = 11;
095:
096: /**
097: * An ellipse outline
098: */
099: public static final int ELLIPSE = 12;
100:
101: /**
102: * A filled ellipse
103: */
104: public static final int SOLID_ELLIPSE = 13;
105:
106: /**
107: * A filled diamond
108: */
109: public static final int SOLID_DIAMOND = 14;
110:
111: /**
112: * An outline diamond
113: */
114: public static final int DIAMOND = 15;
115:
116: /**
117: * A user defined shape drawn in outline
118: */
119: public static final int USER = 16;
120:
121: /**
122: * A user defined shape, filled
123: */
124: public static final int USER_FILL = 17;
125:
126: /**
127: * A user defined shape drawn and filled
128: */
129: public static final int USER_FILL_DRAW = 18;
130:
131: private static double[] lineThickness = { 3.0, 2.0, 1.0, 0.5 };
132:
133: /**
134: * The user defined shape
135: */
136: protected Shape userShape;
137:
138: /**
139: * Constructor for a new XShape
140: */
141: public XShape() {
142: }
143:
144: /**
145: * Fills the shape with the background color
146: * @param g the graphics context
147: */
148: public void paintComponent(Graphics g) {
149: Graphics2D g2d = (Graphics2D) g;
150: Dimension size = getSize();
151: int width = size.width;
152: int height = size.height;
153: if (getComponentCount() > 0) {
154: backgroundImage = new BufferedImage(width, height,
155: BufferedImage.TYPE_INT_ARGB);
156: Graphics2D gbk = (Graphics2D) backgroundImage.getGraphics();
157: super .paintChildren(gbk);
158: gbk.dispose();
159: }
160: if (backgroundImage != null)
161: g2d.setPaint(new TexturePaint(backgroundImage,
162: new Rectangle2D.Double(0, 0, width, height)));//width, height )));
163:
164: Shape s = getShape();
165:
166: switch (mode) {
167: case RECTANGLE:
168: case ORTHO_LINE:
169: case EXTRABOLD_HORIZONTAL:
170: case BOLD_HORIZONTAL:
171: case NORMAL_HORIZONTAL:
172: case THIN_HORIZONTAL:
173: case EXTRABOLD_VERTICAL:
174: case BOLD_VERTICAL:
175: case NORMAL_VERTICAL:
176: case THIN_VERTICAL:
177: case RIGHT_TOP_LINE:
178: case LEFT_TOP_LINE:
179: case SOLID_ELLIPSE:
180: case SOLID_DIAMOND:
181: case USER_FILL:
182: case USER_FILL_DRAW:
183: if (backgroundImage == null)
184: g2d.setColor(getBackground());
185: g2d.fill(s);
186: if (mode != USER_FILL_DRAW)
187: break;
188:
189: case ELLIPSE:
190: case DIAMOND:
191: case USER:
192: g2d.setColor(getForeground());
193: g2d.draw(s);
194: break;
195: }
196: }
197:
198: /**
199: * Paint the child components, this method just consumes the call without doing anything
200: * @param g teh graphics context
201: */
202: public void paintChildren(Graphics g) {
203: }
204:
205: /**
206: * Get shape identifier. The ID is an enumerated constant
207: * @param shapeId the new shape ID.
208: */
209: public void setMode(int shapeId) {
210: mode = shapeId;
211: repaint();
212: }
213:
214: /**
215: * Get shape identifier.
216: * @return the enumerated constant for this shape
217: */
218: public int getMode() {
219: return mode;
220: }
221:
222: /**
223: * Get a shape
224: * @return the generated shape
225: */
226: public Shape getShape() {
227: Dimension d = getSize();
228: GeneralPath gp;
229:
230: switch (mode) {
231: case RECTANGLE:
232: case ORTHO_LINE:
233: return new Rectangle(0, 0, d.width, d.height);
234:
235: case EXTRABOLD_HORIZONTAL:
236: case BOLD_HORIZONTAL:
237: case NORMAL_HORIZONTAL:
238: case THIN_HORIZONTAL:
239: return new Rectangle2D.Double(0, 0, d.width,
240: lineThickness[mode - EXTRABOLD_HORIZONTAL]);
241:
242: case EXTRABOLD_VERTICAL:
243: case BOLD_VERTICAL:
244: case NORMAL_VERTICAL:
245: case THIN_VERTICAL:
246: return new Rectangle2D.Double(0, 0, lineThickness[mode
247: - EXTRABOLD_VERTICAL], d.height);
248:
249: case RIGHT_TOP_LINE:
250: gp = new GeneralPath();
251: gp.moveTo(d.width, 0.0F);
252: gp.lineTo(0.0F, d.height);
253: return gp;
254: case LEFT_TOP_LINE:
255: gp = new GeneralPath();
256: gp.moveTo(0.0F, 0.0F);
257: gp.lineTo(d.width, d.height);
258: return gp;
259:
260: case SOLID_ELLIPSE:
261: case ELLIPSE:
262: return new Ellipse2D.Double(0, 0, d.width - 1.0,
263: d.height - 1.0);
264:
265: case SOLID_DIAMOND:
266: case DIAMOND:
267: gp = new GeneralPath();
268: gp.moveTo(0.0F + d.width / 2.0F, 0.0F);
269: gp.lineTo(0.0F + d.width, 0.0F + d.height / 2.0F);
270: gp.lineTo(0.0F + d.width / 2.0F, 0.0F + d.height);
271: gp.lineTo(0.0F, 0.0F + d.height / 2.0F);
272: gp.closePath();
273: return gp;
274:
275: case USER:
276: case USER_FILL:
277: case USER_FILL_DRAW:
278: if (userShape != null)
279: return userShape;
280: }
281:
282: return getBounds();
283: }
284:
285: /**
286: * Set one or more attributes of the component. Currently this handles the
287: * attributes
288: * <OL>
289: * <LI>mode, value=Cue image filename</LI>
290: * </OL>
291: * @param attribName the attribute name
292: * @param attribValue the attribute value
293: * @return 0 for success, non zero otherwise
294: */
295: public int setAttribute(String attribName, Object attribValue) {
296: if (attribName.equals("mode"))
297: mode = new Integer((String) attribValue).intValue();
298:
299: repaint(100);
300:
301: return 0;
302: }
303:
304: /**
305: * Set a user defiend shape. The shapoe should define a close area is the
306: * mode is set for filling
307: * @param s the user shape
308: * @param fill true to fill the shape
309: */
310: public void setShape(Shape s, boolean fill) {
311: userShape = s;
312: mode = fill ? USER_FILL : USER;
313: repaint();
314: }
315: }
|