Source Code Cross Referenced for XFlowedTextComponent.java in  » XML-UI » xui32 » com » xoetrope » swing » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » XML UI » xui32 » com.xoetrope.swing 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        package com.xoetrope.swing;
002:
003:        import com.xoetrope.swing.animation.AnimationStep;
004:        import com.xoetrope.swing.animation.XAnimationContext;
005:        import com.xoetrope.swing.animation.XAnimationSurface;
006:        import com.xoetrope.swing.util.XShapeGenerator;
007:        import com.xoetrope.util.XTextDefaults;
008:        import java.text.AttributedString;
009:
010:        import java.awt.Component;
011:        import java.awt.Container;
012:        import java.awt.Dimension;
013:        import java.awt.Font;
014:        import java.awt.FontMetrics;
015:        import java.awt.Graphics2D;
016:        import java.awt.Point;
017:        import java.awt.Rectangle;
018:        import java.awt.Shape;
019:        import java.awt.font.FontRenderContext;
020:        import java.awt.font.LineBreakMeasurer;
021:        import java.awt.font.TextAttribute;
022:        import java.awt.font.TextLayout;
023:        import java.awt.geom.AffineTransform;
024:        import java.awt.geom.Area;
025:        import java.awt.geom.Point2D;
026:        import java.awt.geom.Rectangle2D;
027:        import java.text.AttributedCharacterIterator;
028:        import java.text.BreakIterator;
029:        import java.util.ArrayList;
030:        import java.util.Hashtable;
031:        import javax.swing.text.View;
032:        import net.xoetrope.xui.XAttributedComponent;
033:
034:        /**
035:         * A component that flows text around other components, child components and
036:         * components that overlap this component. Assumes that the area within which the 
037:         * text is flowed is composed of rectangular blocks.
038:         *
039:         * <p> Copyright (c) Xoetrope Ltd., 2001-2006, This software is licensed under
040:         * the GNU Public License (GPL), please see license.txt for more details. If
041:         * you make commercial use of this software you must purchase a commercial
042:         * license from Xoetrope.</p>
043:         * <p> $Revision: 1.23 $</p>
044:         */
045:        public class XFlowedTextComponent extends XAnimationSurface //implements XAnimationContext, AnimationStep, XAttributedComponent
046:        {
047:            protected boolean clip;
048:            protected float ascent = 0;
049:            protected Area flowArea;
050:            protected int oX, oY, oW, oH;
051:            protected int deltaX, deltaY;
052:            protected int cols, colSpacing;
053:            protected int currentColumn;
054:
055:            protected Hashtable attributedStrings;
056:
057:            /**
058:             * Create a new flowed text component
059:             */
060:            public XFlowedTextComponent() {
061:                deltaX = 10;
062:                deltaY = 15;
063:                cols = 0;
064:                colSpacing = 10;
065:                autoStart = false;
066:                clip = true;
067:            }
068:
069:            /**
070:             * Set the number of columns in which to divide the flow area
071:             * @param columns the number of columns, if <1 a single flow area is used
072:             */
073:            public void setNumColumns(int columns) {
074:                cols = columns;
075:            }
076:
077:            /**
078:             * Get the number of columns into which the flow area is divided
079:             * @return the number of columns
080:             */
081:            public int getNumColumns() {
082:                return cols;
083:            }
084:
085:            /**
086:             * Set the column spacing as the number of pixels between each column. The 
087:             * spacing has no effect if there is a single column.
088:             * @param spacing the column spacing in pixels
089:             */
090:            public void setColSpacing(int spacing) {
091:                colSpacing = spacing;
092:            }
093:
094:            /**
095:             * Get the column spacing
096:             * @return the spacing in pixels
097:             */
098:            public int getColSpacing() {
099:                return colSpacing;
100:            }
101:
102:            /**
103:             * Set the label/text of the component. Usage depends on the concrete component
104:             * type
105:             * @param text the new text.
106:             */
107:            public void setText(String text) {
108:                super .setText(text);
109:                attributedStrings = null;
110:            }
111:
112:            /**
113:             * Get the label/text of the component.
114:             * @return the component text.
115:             */
116:            public String getText() {
117:                return super .getText();
118:            }
119:
120:            /**
121:             * Set one or more attributes of the component. Currently this handles the
122:             * attributes
123:             * <OL>
124:             * <li>text - set the text</li>
125:             * <li>content - set the text</li>
126:             * <li>increment - set the step size</li>
127:             * <li>cols - the number of columns in which to flow the text, <1 = a single area/column<li>
128:             * </OL>
129:             * @param attribName the attribute name
130:             * @param attribValue the attribute value
131:             * @return 0 for success, non zero otherwise
132:             */
133:            public int setAttribute(String attribName, Object attribValue) {
134:                String attribNameLwr = attribName.toLowerCase();
135:                String attribValueStr = (String) attribValue;
136:                String attribValueLwr = attribValueStr.toLowerCase();
137:                if (attribNameLwr.equals("cols"))
138:                    cols = Integer.parseInt(attribValueLwr);
139:                else if (attribNameLwr.equals("colspacing"))
140:                    colSpacing = Integer.parseInt(attribValueLwr);
141:                else if (attribNameLwr.equals("clip"))
142:                    clip = (attribValueLwr.equals("true") || attribValueLwr
143:                            .equals("1"));
144:                else
145:                    super .setAttribute(attribName, attribValue);
146:                return 0;
147:            }
148:
149:            /**
150:             * Attempts to load and reference the associated view/datastore.
151:             */
152:            public void init() {
153:                super .init();
154:                bimg = null;
155:                Point p = getLocation();
156:                Dimension size = getSize();
157:                oX = p.x;
158:                oY = p.y;
159:                oW = size.width;
160:                oH = size.height;
161:                flowArea = new Area(new Rectangle(oX, oY, oW, oH));
162:
163:                Container parent = (Container) getParent();
164:                int count = parent.getComponentCount();
165:                for (int i = 0; i < count; i++) {
166:                    Component cc = parent.getComponent(i);
167:                    if (cc != this ) {
168:                        Area childArea;
169:                        if (cc instanceof  XShapeGenerator) {
170:                            childArea = new Area(((XShapeGenerator) cc)
171:                                    .getShape());
172:                            Rectangle rect = childArea.getBounds();
173:                            double scale = 1.0 + 20.0 / Math.max(rect.width,
174:                                    rect.height);
175:                            AffineTransform growTransform = AffineTransform
176:                                    .getScaleInstance(scale, scale);
177:
178:                            /*
179:                             * The grow transform needs to move the centre back to the unscaled location
180:                             * with a translate transform
181:                             */
182:                            scale -= 1.0;
183:                            growTransform.translate(-10.0 * scale, -10.0
184:                                    * scale);
185:                            childArea.transform(growTransform);
186:                        } else {
187:                            Rectangle rCC = cc.getBounds();
188:                            rCC.grow(deltaX, deltaY);
189:                            childArea = new Area(rCC);
190:                        }
191:                        flowArea.subtract(childArea);
192:                    }
193:                }
194:                repaint();
195:            }
196:
197:            //=========================================================================
198:            //	    Rendering
199:            //=========================================================================
200:            /**
201:             * Adjust the settings for the next step.
202:             * @param w the width
203:             * @param h the height
204:             */
205:            public void reset(int w, int h) {
206:            }
207:
208:            /**
209:             * Adjust the settings for the next step.
210:             * 
211:             * @param w the width
212:             * @param h the height
213:             */
214:            public void step(int w, int h) {
215:            }
216:
217:            /**
218:             * All classes that extend JAnimationSurface must implement this routine...
219:             * This component renders text in the flow area. The flow area is calculated 
220:             * to be the non-overlapped client area
221:             * @param w the width
222:             * @param h the height
223:             * @param g2 the graphics context
224:             */
225:            public void drawObjects(int w, int h, Graphics2D g2) {
226:                if ((label == null) || (label.length() <= 0))
227:                    return;
228:                if (flowArea == null)
229:                    init();
230:                if (attributedStrings == null)
231:                    attributedStrings = new Hashtable();
232:
233:                applyState(g2);
234:                Font font = getFont();
235:                FontMetrics fm = g2.getFontMetrics(font);
236:                FontRenderContext frc = g2.getFontRenderContext();
237:
238:                // Calculate teh columns areas
239:                Point2D.Double pen = new Point2D.Double(0, 0);
240:                ascent = fm.getAscent();
241:                int numColumns = Math.max(cols, 1);
242:                double columnWidth = (flowArea.getBounds2D().getWidth() - (numColumns == 1 ? 0
243:                        : numColumns * colSpacing))
244:                        / numColumns;
245:                Area[] columns = new Area[numColumns];
246:                double x = flowArea.getBounds().getX();
247:                for (int i = 0; i < numColumns; i++) {
248:                    Area basicColumn = new Area(new Rectangle2D.Double(x, oY,
249:                            columnWidth, oH));
250:                    basicColumn.intersect(flowArea);
251:                    columns[i] = basicColumn;
252:                    x += columnWidth + colSpacing;
253:                }
254:
255:                View v = (View) getClientProperty("html");
256:                if (v != null)
257:                    v.paint(g2, columns[0].getBounds());
258:                else {
259:                    double yPos = 0;
260:                    double currentPos = 0;
261:                    currentColumn = 0;
262:                    label = replace(label, "<br>".subSequence(0, 4),
263:                            XTextDefaults.CRLF_PAIR.subSequence(0,
264:                                    XTextDefaults.CRLF_PAIR.length()));
265:                    int idx = label.indexOf(XTextDefaults.CRLF_PAIR);
266:                    String targetStr = label;
267:                    while (idx > -1) {
268:                        if (idx > 6)
269:                            currentPos = wrapString(g2, targetStr.substring(0,
270:                                    idx), currentPos, yPos, columns);
271:                        currentPos += ascent;
272:                        targetStr = targetStr.substring(idx
273:                                + XTextDefaults.CRLF_PAIR.length());
274:                        idx = targetStr.indexOf(XTextDefaults.CRLF_PAIR);
275:                    }
276:                    yPos = wrapString(g2, targetStr, currentPos, yPos, columns);
277:                }
278:            }
279:
280:            /**
281:             * Apply the current state to the graphics rendering context
282:             * @param g2 the graphics context
283:             */
284:            public void applyState(Graphics2D g2) {
285:                g2.setColor(getForeground());
286:            }
287:
288:            /**
289:             * Draw text that wraps within the flow area
290:             * @param g2 the graphics context
291:             * @param text the text
292:             * @param currentPos the current y offset for a new column
293:             * @param y the current y offset within the column for a new block of text
294:             * @param columns the area of the columns
295:             * @return the latest y position for drawing/rendering
296:             */
297:            protected double wrapString(Graphics2D g2, String text,
298:                    double currentPos, double y, Area[] columns) {
299:                if (text.length() <= 0)
300:                    return y;
301:
302:                Point2D.Double pen = new Point2D.Double(0, currentPos);
303:                float wrappingWidth = oW - 15;
304:                Font font = getFont();
305:
306:                TextLayout layout;
307:                AffineTransform at = AffineTransform.getTranslateInstance(-oX,
308:                        -oY);
309:                FontRenderContext frc = g2.getFontRenderContext();
310:                Object[] cachedRefs = (Object[]) attributedStrings.get(text);
311:                AttributedString as;
312:                int[] lengths;
313:                if (cachedRefs == null) {
314:                    Object[] refs = new Object[2];
315:                    lengths = new int[1];
316:                    refs[0] = as = getAttributedString(text, font, lengths);
317:                    refs[1] = lengths;
318:                    attributedStrings.put(text, refs);
319:                } else {
320:                    as = (AttributedString) cachedRefs[0];
321:                    lengths = (int[]) cachedRefs[1];
322:                }
323:
324:                LineBreakMeasurer measurer = new LineBreakMeasurer(as
325:                        .getIterator(), BreakIterator.getWordInstance(), frc);
326:                int ii = 0;
327:                int len = lengths[0];
328:                try {
329:                    for (int columnIdx = currentColumn; columnIdx < columns.length; columnIdx++) {
330:                        if ((columnIdx > 0) && (measurer.getPosition() < len))
331:                            pen.y = currentPos;
332:                        while ((measurer.getPosition() < len) && (pen.y < oH)) {
333:                            ii++;
334:                            Rectangle2D.Double rLine = new Rectangle2D.Double(
335:                                    oX, oY + pen.y, oW, ascent);
336:                            Area aArea = new Area(rLine);
337:                            if (flowArea != null)
338:                                aArea.intersect(columns[columnIdx]);
339:                            Shape s = at.createTransformedShape(aArea);
340:                            Rectangle r = s.getBounds();
341:                            int w = (int) r.getWidth();
342:                            if (w > 15)
343:                                layout = measurer.nextLayout(w - 15);
344:                            else
345:                                layout = null;
346:                            pen.y += ascent;
347:                            if (layout == null)
348:                                continue;
349:                            else
350:                                layout
351:                                        .draw(g2, (float) r.getX(),
352:                                                (float) pen.y);
353:
354:                            // Only increment the current column index when something has actually 
355:                            // been drawn in the column. If we get this far then something has 
356:                            // been drawn
357:                            currentColumn = columnIdx;
358:                        }
359:                        currentPos = y;
360:                    }
361:                } catch (Exception ex1) {
362:                    ex1.printStackTrace();
363:                }
364:                return pen.y;
365:            }
366:
367:            /**
368:             * Get an AttribtedString for this component, converting the tags
369:             * &lt;b&gt;, &lt;i&gt;, &lt;u&gt;, &lt;sub&gt;, &lt;super&gt;, &lt;swap&gt;, &lt;justify&gt;, &lt;strike&gt;
370:             * to the proper internal form.
371:             * @param localCopy the text being rendered
372:             * @param font the current font
373:             * @param lengths on return contains the length of the text to be rendered - the argument should be a string[1]
374:             * @return the new AttributedString
375:             */
376:            protected AttributedString getAttributedString(String localCopy,
377:                    Font font, int[] lengths) {
378:                ArrayList attributes = new ArrayList();
379:
380:                String[] startTags = { "<b>", "<i>", "<u>", "<sub>", "<super>",
381:                        "<swap>", "<justify>", "<strike>" };
382:                String[] endTags = { "</b>", "</i>", "</u>", "</sub>",
383:                        "</super>", "</swap>", "</justify>", "</strike>" };
384:                AttributedCharacterIterator.Attribute[] keys = {
385:                        TextAttribute.WEIGHT, TextAttribute.POSTURE,
386:                        TextAttribute.UNDERLINE, TextAttribute.SUPERSCRIPT,
387:                        TextAttribute.SUPERSCRIPT, TextAttribute.SWAP_COLORS,
388:                        TextAttribute.JUSTIFICATION,
389:                        TextAttribute.STRIKETHROUGH };
390:                for (int i = 0; i < startTags.length; i++) {
391:                    int pos = localCopy.indexOf(startTags[i]);
392:                    while (pos >= 0) {
393:                        int endPos = localCopy.indexOf(endTags[i]);
394:                        if (endPos > pos) {
395:                            int tagLen = startTags[i].length();
396:                            localCopy = localCopy.substring(0, pos)
397:                                    + localCopy.substring(pos + tagLen, endPos)
398:                                    + localCopy.substring(endPos + tagLen + 1);
399:                            Object value = null;
400:                            switch (i) {
401:                            case 0: //TextAttribute.WEIGHT:
402:                                value = new Float(TextAttribute.WEIGHT_BOLD
403:                                        .floatValue());
404:                                break;
405:                            case 1: //TextAttribute.POSTURE:
406:                                value = new Float(TextAttribute.POSTURE_OBLIQUE
407:                                        .floatValue());
408:                                break;
409:                            case 2: //TextAttribute.UNDERLINE:
410:                                value = new Float(TextAttribute.UNDERLINE_ON
411:                                        .floatValue());
412:                                break;
413:                            case 3: //TextAttribute.SUPERSCRIPT:
414:                            case 4: //TextAttribute.SUPERSCRIPT:
415:                                value = new Float(
416:                                        i == 3 ? TextAttribute.SUPERSCRIPT_SUPER
417:                                                .floatValue()
418:                                                : TextAttribute.SUPERSCRIPT_SUB
419:                                                        .floatValue());
420:                                break;
421:                            case 5: //TextAttribute.SWAP_COLORS:
422:                                value = TextAttribute.SWAP_COLORS_ON;
423:                                break;
424:                            case 6: //TextAttribute.JUSTIFICATION:
425:                                value = new Float(
426:                                        TextAttribute.JUSTIFICATION_FULL
427:                                                .floatValue());
428:                                break;
429:                            case 7: //TextAttribute.STRIKETHROUGH:
430:                                value = TextAttribute.STRIKETHROUGH_ON;
431:                                break;
432:                            }
433:                            int numAttribs = attributes.size();
434:                            for (int j = 0; j < numAttribs; j++) {
435:                                Attrib attr = (Attrib) attributes.get(j);
436:                                if (attr.start > pos)
437:                                    attr.start -= tagLen;
438:                                if (attr.end > pos)
439:                                    attr.end -= tagLen;
440:                                if (attr.start > endPos)
441:                                    attr.start -= tagLen + 1;
442:                                if (attr.end > endPos)
443:                                    attr.end -= tagLen + 1;
444:                            }
445:                            attributes.add(new Attrib(keys[i], value, pos,
446:                                    endPos - tagLen));
447:                        }
448:                        pos = localCopy.indexOf(startTags[i]);
449:                    }
450:                }
451:
452:                AttributedString as = new AttributedString(localCopy, font
453:                        .getAttributes());
454:                int numAttribs = attributes.size();
455:                for (int i = 0; i < numAttribs; i++) {
456:                    Attrib attr = (Attrib) attributes.get(i);
457:                    as
458:                            .addAttribute(attr.type, attr.value, attr.start,
459:                                    attr.end);
460:                }
461:                lengths[0] = localCopy.length();
462:                return as;
463:            }
464:
465:            /**
466:             * Set the clip state
467:             * @param state true to clip siblings
468:             */
469:            public void setClip(boolean state) {
470:                clip = state;
471:                init();
472:                repaint();
473:            }
474:
475:            /**
476:             * Get the clip state
477:             * @return true if siblings are clipped
478:             */
479:            public boolean getClip() {
480:                return clip;
481:            }
482:
483:            /**
484:             * A structure for holding references to the attributes of the string
485:             */
486:            protected class Attrib {
487:                int start, end;
488:                AttributedCharacterIterator.Attribute type;
489:                Object value;
490:
491:                /**
492:                 * Create a new Attrib holder
493:                 * @param t the type of attribute
494:                 * @param v the value of the attribute
495:                 * @param s the starting offset
496:                 * @param e the ending offset
497:                 */
498:                public Attrib(AttributedCharacterIterator.Attribute t,
499:                        Object v, int s, int e) {
500:                    type = t;
501:                    value = v;
502:                    start = s;
503:                    end = e;
504:                }
505:            }
506:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.