Source Code Cross Referenced for BasicHTML.java in  » 6.0-JDK-Core » swing » javax » swing » plaf » basic » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
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
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » swing » javax.swing.plaf.basic 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 1998-2006 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025        package javax.swing.plaf.basic;
026
027        import java.io.*;
028        import java.awt.*;
029        import java.net.URL;
030
031        import javax.swing.*;
032        import javax.swing.text.*;
033        import javax.swing.text.html.*;
034
035        import sun.swing.SwingUtilities2;
036
037        /**
038         * Support for providing html views for the swing components.
039         * This translates a simple html string to a javax.swing.text.View
040         * implementation that can render the html and provide the necessary
041         * layout semantics.
042         *
043         * @author  Timothy Prinzing
044         * @version 1.33 05/05/07
045         * @since 1.3
046         */
047        public class BasicHTML {
048
049            /**
050             * Create an html renderer for the given component and
051             * string of html.
052             */
053            public static View createHTMLView(JComponent c, String html) {
054                BasicEditorKit kit = getFactory();
055                Document doc = kit.createDefaultDocument(c.getFont(), c
056                        .getForeground());
057                Object base = c.getClientProperty(documentBaseKey);
058                if (base instanceof  URL) {
059                    ((HTMLDocument) doc).setBase((URL) base);
060                }
061                Reader r = new StringReader(html);
062                try {
063                    kit.read(r, doc, 0);
064                } catch (Throwable e) {
065                }
066                ViewFactory f = kit.getViewFactory();
067                View hview = f.create(doc.getDefaultRootElement());
068                View v = new Renderer(c, f, hview);
069                return v;
070            }
071
072            /**
073             * Returns the baseline for the html renderer.
074             *
075             * @param view the View to get the baseline for
076             * @param w the width to get the baseline for
077             * @param h the height to get the baseline for
078             * @throws IllegalArgumentException if width or height is < 0
079             * @return baseline or a value < 0 indicating there is no reasonable
080             *                  baseline
081             * @see java.awt.FontMetrics
082             * @see javax.swing.JComponent#getBaseline(int,int)
083             * @since 1.6
084             */
085            public static int getHTMLBaseline(View view, int w, int h) {
086                if (w < 0 || h < 0) {
087                    throw new IllegalArgumentException(
088                            "Width and height must be >= 0");
089                }
090                if (view instanceof  Renderer) {
091                    return getBaseline(view.getView(0), w, h);
092                }
093                return -1;
094            }
095
096            /**
097             * Gets the baseline for the specified component.  This digs out
098             * the View client property, and if non-null the baseline is calculated
099             * from it.  Otherwise the baseline is the value <code>y + ascent</code>.
100             */
101            static int getBaseline(JComponent c, int y, int ascent, int w, int h) {
102                View view = (View) c.getClientProperty(BasicHTML.propertyKey);
103                if (view != null) {
104                    int baseline = getHTMLBaseline(view, w, h);
105                    if (baseline < 0) {
106                        return baseline;
107                    }
108                    return y + baseline;
109                }
110                return y + ascent;
111            }
112
113            /**
114             * Gets the baseline for the specified View.
115             */
116            static int getBaseline(View view, int w, int h) {
117                if (hasParagraph(view)) {
118                    view.setSize(w, h);
119                    return getBaseline(view, new Rectangle(0, 0, w, h));
120                }
121                return -1;
122            }
123
124            private static int getBaseline(View view, Shape bounds) {
125                if (view.getViewCount() == 0) {
126                    return -1;
127                }
128                AttributeSet attributes = view.getElement().getAttributes();
129                Object name = null;
130                if (attributes != null) {
131                    name = attributes
132                            .getAttribute(StyleConstants.NameAttribute);
133                }
134                int index = 0;
135                if (name == HTML.Tag.HTML && view.getViewCount() > 1) {
136                    // For html on widgets the header is not visible, skip it.
137                    index++;
138                }
139                bounds = view.getChildAllocation(index, bounds);
140                if (bounds == null) {
141                    return -1;
142                }
143                View child = view.getView(index);
144                if (view instanceof  javax.swing.text.ParagraphView) {
145                    Rectangle rect;
146                    if (bounds instanceof  Rectangle) {
147                        rect = (Rectangle) bounds;
148                    } else {
149                        rect = bounds.getBounds();
150                    }
151                    return rect.y
152                            + (int) (rect.height * child
153                                    .getAlignment(View.Y_AXIS));
154                }
155                return getBaseline(child, bounds);
156            }
157
158            private static boolean hasParagraph(View view) {
159                if (view instanceof  javax.swing.text.ParagraphView) {
160                    return true;
161                }
162                if (view.getViewCount() == 0) {
163                    return false;
164                }
165                AttributeSet attributes = view.getElement().getAttributes();
166                Object name = null;
167                if (attributes != null) {
168                    name = attributes
169                            .getAttribute(StyleConstants.NameAttribute);
170                }
171                int index = 0;
172                if (name == HTML.Tag.HTML && view.getViewCount() > 1) {
173                    // For html on widgets the header is not visible, skip it.
174                    index = 1;
175                }
176                return hasParagraph(view.getView(index));
177            }
178
179            /**
180             * Check the given string to see if it should trigger the
181             * html rendering logic in a non-text component that supports 
182             * html rendering.
183             */
184            public static boolean isHTMLString(String s) {
185                if (s != null) {
186                    if ((s.length() >= 6) && (s.charAt(0) == '<')
187                            && (s.charAt(5) == '>')) {
188                        String tag = s.substring(1, 5);
189                        return tag.equalsIgnoreCase(propertyKey);
190                    }
191                }
192                return false;
193            }
194
195            /**
196             * Stash the HTML render for the given text into the client
197             * properties of the given JComponent. If the given text is 
198             * <em>NOT HTML</em> the property will be cleared of any
199             * renderer.
200             * <p>
201             * This method is useful for ComponentUI implementations
202             * that are static (i.e. shared) and get their state
203             * entirely from the JComponent.
204             */
205            public static void updateRenderer(JComponent c, String text) {
206                View value = null;
207                View oldValue = (View) c
208                        .getClientProperty(BasicHTML.propertyKey);
209                Boolean htmlDisabled = (Boolean) c
210                        .getClientProperty(htmlDisable);
211                if (htmlDisabled != Boolean.TRUE
212                        && BasicHTML.isHTMLString(text)) {
213                    value = BasicHTML.createHTMLView(c, text);
214                }
215                if (value != oldValue && oldValue != null) {
216                    for (int i = 0; i < oldValue.getViewCount(); i++) {
217                        oldValue.getView(i).setParent(null);
218                    }
219                }
220                c.putClientProperty(BasicHTML.propertyKey, value);
221            }
222
223            /**
224             * If this client property of a JComponent is set to Boolean.TRUE
225             * the component's 'text' property is never treated as HTML.
226             */
227            private static final String htmlDisable = "html.disable";
228
229            /**
230             * Key to use for the html renderer when stored as a 
231             * client property of a JComponent.
232             */
233            public static final String propertyKey = "html";
234
235            /**
236             * Key stored as a client property to indicate the base that relative
237             * references are resolved against. For example, lets say you keep
238             * your images in the directory resources relative to the code path,
239             * you would use the following the set the base:
240             * <pre>
241             *   jComponent.putClientProperty(documentBaseKey,
242             *                                xxx.class.getResource("resources/"));
243             * </pre>
244             */
245            public static final String documentBaseKey = "html.base";
246
247            static BasicEditorKit getFactory() {
248                if (basicHTMLFactory == null) {
249                    basicHTMLViewFactory = new BasicHTMLViewFactory();
250                    basicHTMLFactory = new BasicEditorKit();
251                }
252                return basicHTMLFactory;
253            }
254
255            /**
256             * The source of the html renderers
257             */
258            private static BasicEditorKit basicHTMLFactory;
259
260            /**
261             * Creates the Views that visually represent the model.
262             */
263            private static ViewFactory basicHTMLViewFactory;
264
265            /**
266             * Overrides to the default stylesheet.  Should consider
267             * just creating a completely fresh stylesheet.
268             */
269            private static final String styleChanges = "p { margin-top: 0; margin-bottom: 0; margin-left: 0; margin-right: 0 }"
270                    + "body { margin-top: 0; margin-bottom: 0; margin-left: 0; margin-right: 0 }";
271
272            /**
273             * The views produced for the ComponentUI implementations aren't
274             * going to be edited and don't need full html support.  This kit
275             * alters the HTMLEditorKit to try and trim things down a bit.  
276             * It does the following:
277             * <ul>
278             * <li>It doesn't produce Views for things like comments, 
279             * head, title, unknown tags, etc.  
280             * <li>It installs a different set of css settings from the default
281             * provided by HTMLEditorKit.
282             * </ul>
283             */
284            static class BasicEditorKit extends HTMLEditorKit {
285                /** Shared base style for all documents created by us use. */
286                private static StyleSheet defaultStyles;
287
288                /**
289                 * Overriden to return our own slimmed down style sheet.
290                 */
291                public StyleSheet getStyleSheet() {
292                    if (defaultStyles == null) {
293                        defaultStyles = new StyleSheet();
294                        StringReader r = new StringReader(styleChanges);
295                        try {
296                            defaultStyles.loadRules(r, null);
297                        } catch (Throwable e) {
298                            // don't want to die in static initialization... 
299                            // just display things wrong.
300                        }
301                        r.close();
302                        defaultStyles.addStyleSheet(super .getStyleSheet());
303                    }
304                    return defaultStyles;
305                }
306
307                /**
308                 * Sets the async policy to flush everything in one chunk, and
309                 * to not display unknown tags.
310                 */
311                public Document createDefaultDocument(Font defaultFont,
312                        Color foreground) {
313                    StyleSheet styles = getStyleSheet();
314                    StyleSheet ss = new StyleSheet();
315                    ss.addStyleSheet(styles);
316                    BasicDocument doc = new BasicDocument(ss, defaultFont,
317                            foreground);
318                    doc.setAsynchronousLoadPriority(Integer.MAX_VALUE);
319                    doc.setPreservesUnknownTags(false);
320                    return doc;
321                }
322
323                /**
324                 * Returns the ViewFactory that is used to make sure the Views don't
325                 * load in the background.
326                 */
327                public ViewFactory getViewFactory() {
328                    return basicHTMLViewFactory;
329                }
330            }
331
332            /**
333             * BasicHTMLViewFactory extends HTMLFactory to force images to be loaded
334             * synchronously.
335             */
336            static class BasicHTMLViewFactory extends HTMLEditorKit.HTMLFactory {
337                public View create(Element elem) {
338                    View view = super .create(elem);
339
340                    if (view instanceof  ImageView) {
341                        ((ImageView) view).setLoadsSynchronously(true);
342                    }
343                    return view;
344                }
345            }
346
347            /**
348             * The subclass of HTMLDocument that is used as the model. getForeground
349             * is overridden to return the foreground property from the Component this
350             * was created for.
351             */
352            static class BasicDocument extends HTMLDocument {
353                /** The host, that is where we are rendering. */
354                // private JComponent host;
355                BasicDocument(StyleSheet s, Font defaultFont, Color foreground) {
356                    super (s);
357                    setPreservesUnknownTags(false);
358                    setFontAndColor(defaultFont, foreground);
359                }
360
361                /**
362                 * Sets the default font and default color. These are set by
363                 * adding a rule for the body that specifies the font and color.
364                 * This allows the html to override these should it wish to have
365                 * a custom font or color.
366                 */
367                private void setFontAndColor(Font font, Color fg) {
368                    getStyleSheet().addRule(
369                            sun.swing.SwingUtilities2.displayPropertiesToCSS(
370                                    font, fg));
371                }
372            }
373
374            /**
375             * Root text view that acts as an HTML renderer.
376             */
377            static class Renderer extends View {
378
379                Renderer(JComponent c, ViewFactory f, View v) {
380                    super (null);
381                    host = c;
382                    factory = f;
383                    view = v;
384                    view.setParent(this );
385                    // initially layout to the preferred size
386                    setSize(view.getPreferredSpan(X_AXIS), view
387                            .getPreferredSpan(Y_AXIS));
388                }
389
390                /**
391                 * Fetches the attributes to use when rendering.  At the root
392                 * level there are no attributes.  If an attribute is resolved
393                 * up the view hierarchy this is the end of the line.
394                 */
395                public AttributeSet getAttributes() {
396                    return null;
397                }
398
399                /**
400                 * Determines the preferred span for this view along an axis.
401                 *
402                 * @param axis may be either X_AXIS or Y_AXIS
403                 * @return the span the view would like to be rendered into.
404                 *         Typically the view is told to render into the span
405                 *         that is returned, although there is no guarantee.
406                 *         The parent may choose to resize or break the view.
407                 */
408                public float getPreferredSpan(int axis) {
409                    if (axis == X_AXIS) {
410                        // width currently laid out to
411                        return width;
412                    }
413                    return view.getPreferredSpan(axis);
414                }
415
416                /**
417                 * Determines the minimum span for this view along an axis.
418                 *
419                 * @param axis may be either X_AXIS or Y_AXIS
420                 * @return the span the view would like to be rendered into.
421                 *         Typically the view is told to render into the span
422                 *         that is returned, although there is no guarantee.
423                 *         The parent may choose to resize or break the view.
424                 */
425                public float getMinimumSpan(int axis) {
426                    return view.getMinimumSpan(axis);
427                }
428
429                /**
430                 * Determines the maximum span for this view along an axis.
431                 *
432                 * @param axis may be either X_AXIS or Y_AXIS
433                 * @return the span the view would like to be rendered into.
434                 *         Typically the view is told to render into the span
435                 *         that is returned, although there is no guarantee.
436                 *         The parent may choose to resize or break the view.
437                 */
438                public float getMaximumSpan(int axis) {
439                    return Integer.MAX_VALUE;
440                }
441
442                /**
443                 * Specifies that a preference has changed.
444                 * Child views can call this on the parent to indicate that
445                 * the preference has changed.  The root view routes this to
446                 * invalidate on the hosting component.
447                 * <p>
448                 * This can be called on a different thread from the
449                 * event dispatching thread and is basically unsafe to
450                 * propagate into the component.  To make this safe,
451                 * the operation is transferred over to the event dispatching 
452                 * thread for completion.  It is a design goal that all view
453                 * methods be safe to call without concern for concurrency,
454                 * and this behavior helps make that true.
455                 *
456                 * @param child the child view
457                 * @param width true if the width preference has changed
458                 * @param height true if the height preference has changed
459                 */
460                public void preferenceChanged(View child, boolean width,
461                        boolean height) {
462                    host.revalidate();
463                    host.repaint();
464                }
465
466                /**
467                 * Determines the desired alignment for this view along an axis.
468                 *
469                 * @param axis may be either X_AXIS or Y_AXIS
470                 * @return the desired alignment, where 0.0 indicates the origin
471                 *     and 1.0 the full span away from the origin
472                 */
473                public float getAlignment(int axis) {
474                    return view.getAlignment(axis);
475                }
476
477                /**
478                 * Renders the view.
479                 *
480                 * @param g the graphics context
481                 * @param allocation the region to render into
482                 */
483                public void paint(Graphics g, Shape allocation) {
484                    Rectangle alloc = allocation.getBounds();
485                    view.setSize(alloc.width, alloc.height);
486                    view.paint(g, allocation);
487                }
488
489                /**
490                 * Sets the view parent.
491                 *
492                 * @param parent the parent view
493                 */
494                public void setParent(View parent) {
495                    throw new Error("Can't set parent on root view");
496                }
497
498                /** 
499                 * Returns the number of views in this view.  Since
500                 * this view simply wraps the root of the view hierarchy
501                 * it has exactly one child.
502                 *
503                 * @return the number of views
504                 * @see #getView
505                 */
506                public int getViewCount() {
507                    return 1;
508                }
509
510                /** 
511                 * Gets the n-th view in this container.
512                 *
513                 * @param n the number of the view to get
514                 * @return the view
515                 */
516                public View getView(int n) {
517                    return view;
518                }
519
520                /**
521                 * Provides a mapping from the document model coordinate space
522                 * to the coordinate space of the view mapped to it.
523                 *
524                 * @param pos the position to convert
525                 * @param a the allocated region to render into
526                 * @return the bounding box of the given position
527                 */
528                public Shape modelToView(int pos, Shape a, Position.Bias b)
529                        throws BadLocationException {
530                    return view.modelToView(pos, a, b);
531                }
532
533                /**
534                 * Provides a mapping from the document model coordinate space
535                 * to the coordinate space of the view mapped to it.
536                 *
537                 * @param p0 the position to convert >= 0
538                 * @param b0 the bias toward the previous character or the
539                 *  next character represented by p0, in case the 
540                 *  position is a boundary of two views. 
541                 * @param p1 the position to convert >= 0
542                 * @param b1 the bias toward the previous character or the
543                 *  next character represented by p1, in case the 
544                 *  position is a boundary of two views. 
545                 * @param a the allocated region to render into
546                 * @return the bounding box of the given position is returned
547                 * @exception BadLocationException  if the given position does
548                 *   not represent a valid location in the associated document
549                 * @exception IllegalArgumentException for an invalid bias argument
550                 * @see View#viewToModel
551                 */
552                public Shape modelToView(int p0, Position.Bias b0, int p1,
553                        Position.Bias b1, Shape a) throws BadLocationException {
554                    return view.modelToView(p0, b0, p1, b1, a);
555                }
556
557                /**
558                 * Provides a mapping from the view coordinate space to the logical
559                 * coordinate space of the model.
560                 *
561                 * @param x x coordinate of the view location to convert
562                 * @param y y coordinate of the view location to convert
563                 * @param a the allocated region to render into
564                 * @return the location within the model that best represents the
565                 *    given point in the view
566                 */
567                public int viewToModel(float x, float y, Shape a,
568                        Position.Bias[] bias) {
569                    return view.viewToModel(x, y, a, bias);
570                }
571
572                /**
573                 * Returns the document model underlying the view.
574                 *
575                 * @return the model
576                 */
577                public Document getDocument() {
578                    return view.getDocument();
579                }
580
581                /**
582                 * Returns the starting offset into the model for this view.
583                 *
584                 * @return the starting offset
585                 */
586                public int getStartOffset() {
587                    return view.getStartOffset();
588                }
589
590                /**
591                 * Returns the ending offset into the model for this view.
592                 *
593                 * @return the ending offset
594                 */
595                public int getEndOffset() {
596                    return view.getEndOffset();
597                }
598
599                /**
600                 * Gets the element that this view is mapped to.
601                 *
602                 * @return the view
603                 */
604                public Element getElement() {
605                    return view.getElement();
606                }
607
608                /**
609                 * Sets the view size.
610                 *
611                 * @param width the width
612                 * @param height the height
613                 */
614                public void setSize(float width, float height) {
615                    this .width = (int) width;
616                    view.setSize(width, height);
617                }
618
619                /**
620                 * Fetches the container hosting the view.  This is useful for
621                 * things like scheduling a repaint, finding out the host 
622                 * components font, etc.  The default implementation
623                 * of this is to forward the query to the parent view.
624                 *
625                 * @return the container
626                 */
627                public Container getContainer() {
628                    return host;
629                }
630
631                /**
632                 * Fetches the factory to be used for building the
633                 * various view fragments that make up the view that
634                 * represents the model.  This is what determines
635                 * how the model will be represented.  This is implemented
636                 * to fetch the factory provided by the associated
637                 * EditorKit.
638                 *
639                 * @return the factory
640                 */
641                public ViewFactory getViewFactory() {
642                    return factory;
643                }
644
645                private int width;
646                private View view;
647                private ViewFactory factory;
648                private JComponent host;
649
650            }
651        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.