001: package com.xoetrope.tools;
002:
003: import java.awt.AlphaComposite;
004: import java.awt.Color;
005: import java.awt.Composite;
006: import java.awt.Font;
007: import java.awt.FontMetrics;
008: import java.awt.Graphics2D;
009: import java.awt.Rectangle;
010: import java.awt.RenderingHints;
011: import java.awt.geom.AffineTransform;
012: import java.awt.geom.Area;
013: import java.awt.geom.Ellipse2D;
014: import java.awt.geom.Rectangle2D;
015: import java.util.Hashtable;
016: import javax.swing.JComponent;
017: import net.xoetrope.swing.painter.XTitlePainter;
018:
019: /**
020: *
021: * @author kingsley.elmes
022: */
023: public class XCircularBackground implements XTitlePainter {
024: protected double radians, min, w, h;
025: protected Ellipse2D.Double smallEllipse, bigEllipse;
026: protected String centreText, rotatedText;
027: protected double inflation = 10.0;
028: protected boolean alignTopLeft = true;
029: private Font font;
030:
031: private Hashtable<String, Double> tokenMetrics;
032:
033: /** Creates a new instance of XCircularBackground */
034: public XCircularBackground() {
035: tokenMetrics = new Hashtable<String, Double>();
036: }
037:
038: public void paint(Graphics2D g, JComponent obj, int width,
039: int height) {
040: Graphics2D g2d = (Graphics2D) g.create();
041:
042: g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
043: RenderingHints.VALUE_ANTIALIAS_ON);
044: g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
045: RenderingHints.VALUE_RENDER_QUALITY);
046:
047: Composite composite = g2d.getComposite();
048: Composite fade = AlphaComposite.getInstance(
049: AlphaComposite.SRC_OVER, 0.5f);
050: g2d.setComposite(fade);
051:
052: g2d.setColor(new Color(0xFFEEBB));
053:
054: w = (double) width;
055: h = (double) height;
056: min = Math.min(w, h);
057: double ratio = 4.0;
058: double fraction = 1.0 / (ratio + 1);
059: double smallDimension = min * fraction;
060: double bigDimension = min * ratio * fraction;
061:
062: double x1 = (width - bigDimension) / 2.0;
063: double y1 = (height - bigDimension) / 2.0;
064: bigEllipse = new Ellipse2D.Double(x1, y1, bigDimension,
065: bigDimension);
066:
067: double cx = x1 + bigDimension / 2.0;
068: double cy = y1 + bigDimension / 2.0;
069:
070: Area area = new Area(bigEllipse);
071:
072: double x2 = x1 - smallDimension;
073: double y2 = y1 + (bigDimension - smallDimension) / 2.0;
074:
075: smallEllipse = new Ellipse2D.Double(x2, y2, smallDimension
076: + inflation, smallDimension + inflation);
077: area.add(new Area(smallEllipse));
078:
079: // Translate to the origin and then rotate
080: AffineTransform at = AffineTransform.getTranslateInstance(-cx,
081: -cy);
082: at.rotate(radians, bigEllipse.getCenterX(), bigEllipse
083: .getCenterY());
084: area.transform(at);
085:
086: double dx = 0.0, dy = 0.0;
087: if (isAlignTopLeft()) {
088: Rectangle2D bounds = area.getBounds2D();
089: dx = (w / 2.0) + bounds.getX();
090: dy = (h / 2.0) + bounds.getY();
091: }
092:
093: // Translate back to the centre
094: at = AffineTransform.getTranslateInstance(cx - dx, cy - dy);
095: area.transform(at);
096: g2d.fill(area);
097:
098: g2d.translate(-dx, -dy);
099: drawRotatedText(g2d, bigEllipse.getBounds2D());
100: drawCentreText(g2d, bigEllipse.getBounds2D());
101:
102: // XFlowedTextComponent flowedText = new XFlowedTextComponent();
103: // flowedText.setBounds( bigEllipse.getBounds() );
104: // flowedText.setText( centreText );
105: // obj.add( flowedText );
106: // flowedText.init();
107:
108: g2d.dispose();
109: }
110:
111: public void setCircleRotation(double angle) {
112: radians = Math.toRadians(angle);
113: }
114:
115: private void drawCentreText(Graphics2D g2d, Rectangle2D rect) {
116: if (centreText != null) {
117: Ellipse2D.Double bounds = new Ellipse2D.Double(
118: rect.getX() + 40.0, rect.getY() + 40.0, rect
119: .getWidth() - 80.0, rect.getHeight() - 80.0);
120: Ellipse2D.Double innerCircle = new Ellipse2D.Double(rect
121: .getX() + 30.0, rect.getY() + 30.0,
122: rect.getWidth() - 60.0, rect.getHeight() - 60.0);
123: // g2d.fill( innerCircle );
124:
125: Composite fade = AlphaComposite.getInstance(
126: AlphaComposite.SRC_OVER, 1.0F);
127: g2d.setComposite(fade);
128:
129: Font font = getFont();
130: g2d.setColor(Color.white);
131: g2d.setFont(font);
132:
133: String[] tokens = centreText.split("\\s+");
134: Area area = new Area(bounds);
135: Rectangle rectArea = area.getBounds();
136: FontMetrics fm = g2d.getFontMetrics();
137:
138: double x = bounds.getX();
139: double y = bounds.getY() + 5;
140:
141: int i = 0;
142: boolean finished = false;
143: while (finished == false) {
144: while (x < (bounds.getX() + bounds.getWidth())) {
145: double wordWidth;
146: Double metric = tokenMetrics.get(tokens[i]);
147: if (metric != null)
148: wordWidth = metric.doubleValue();
149: else {
150: wordWidth = fm.getStringBounds(tokens[i], g2d)
151: .getWidth();
152: tokenMetrics.put(tokens[i], new Double(
153: wordWidth));
154: }
155:
156: if (rectArea.contains(x, y) && area.contains(x, y)
157: && area.contains(x + wordWidth, y)) {
158: g2d.setColor(Color.black);
159: g2d.drawString(tokens[i], (int) x + 1,
160: (int) y + 1);
161: g2d.setColor(Color.white);
162: g2d.drawString(tokens[i], (int) x, (int) y);
163: x = x + (wordWidth + 3);
164: i += 1;
165:
166: if (i == tokens.length) {
167: finished = true;
168: break;
169: }
170: } else {
171: x += 1;
172: }
173: }
174: y += fm.getStringBounds(tokens[0], g2d).getHeight();
175: x = bounds.getX();
176: }
177: }
178: }
179:
180: private void drawRotatedText(Graphics2D g2d, Rectangle2D bounds) {
181: if (rotatedText != null) {
182: String[] tokens = rotatedText.split("(?<=[\\w\\s])");
183:
184: Font font = new Font("Arial", Font.BOLD, 21);
185: g2d.setColor(Color.black);
186: g2d.setFont(font);
187:
188: FontMetrics fm = g2d.getFontMetrics();
189:
190: int x = (int) bounds.getCenterX();
191: int y = (int) (bounds.getCenterY()
192: - (bounds.getHeight() / 2.0) + fm.getHeight());
193:
194: double degrees = 0;
195: for (int i = 0; i < tokens.length; i++) {
196: g2d.rotate(Math.toRadians(degrees),
197: bounds.getCenterX(), bounds.getCenterY());
198: g2d.drawString(tokens[i], x, y);
199: g2d.rotate(Math.toRadians(-degrees), bounds
200: .getCenterX(), bounds.getCenterY());
201:
202: double wordWidth;
203: Double metric = tokenMetrics.get(tokens[i]);
204: if (metric != null)
205: wordWidth = metric.doubleValue();
206: else {
207: wordWidth = fm.getStringBounds(tokens[i], g2d)
208: .getWidth();
209: tokenMetrics.put(tokens[i], new Double(wordWidth));
210: }
211:
212: degrees = degrees + (wordWidth / 2.5);
213: }
214: }
215: }
216:
217: public void setCenterText(String t) {
218: centreText = t;
219: }
220:
221: public void setRotatedText(String t) {
222: rotatedText = t;
223: }
224:
225: public void setBlend(boolean b) {
226: }
227:
228: public void setTitle(String text) {
229: }
230:
231: public void setTitleColor(Color c) {
232: }
233:
234: public void setTitleTextColor(Color c) {
235: }
236:
237: public void setTitleFont(Font f) {
238: }
239:
240: public void setTitlePosition(int pos) {
241: }
242:
243: public boolean isAlignTopLeft() {
244: return alignTopLeft;
245: }
246:
247: public void setAlignTopLeft(boolean alignTopLeft) {
248: this .alignTopLeft = alignTopLeft;
249: }
250:
251: public Font getFont() {
252: return font;
253: }
254:
255: public void setFont(Font font) {
256: this .font = font;
257: }
258:
259: public void paint(Graphics2D g, Object object, int width, int height) {
260: }
261: }
|