JavaSwingText components and DocumentViews: Views, elements and properties


Views, elements and properties

Document elements are displayed in text components by Views. This discussion focuses on where and how this mapping takes place and how the view implementations take properties from the Document and the element's attribute set.

Some short comments about the HTML package are included here. The RTF package doesn't introduce new views or mappings.

Standard painting Views

There are only few views that actually paint, the others are concerned with grouping and layouting children views. More specifically, the background is almost never painted, even when set.

Plain View / WrappedPlainView (used for JTextArea)

GlyphView (using a GlyphPainter)

LabelView (subclass of GlyphView)

Special views

HTML views

Mapping Elements to Views

Role of TextUI / EditorKit

Every text component (component that has TextUI) has an "editor kit" assigned to it by the UI. With JEditorPane/JTextPane this becomes a property of the component itself, with JTextField and JTextArea it is managed by the UI alone (probably once shared instance).

This editor kit gives access to a view factory, which creates views for elements (possibly only for those elements contained in documents compatible with the editor kit).

It is up the LookAndFeel class(es) to listen for changes of the "document" property (or other properties that could affect representation of elements) and (re)create the Views, using the given view factory (which can be replaced by something custom for JEditorPane/JTextPane and it provided by the TextUI itself for JTextField/JTextArea), or (maybe) fall back to some default if the editor kit hasn't got a view factory (it is unclear whether this is allowed, but DefaultEditorKit does it).

Understanding the behaviour the BasicTextXXXUI classes is complicated because much is handled in BasicTextUI, both for the editor-kit having and the editor-kit less components.

BasicTextUI provides a RootView class that serves as root view, not representing an element itself. Its getViewFactory method returns the editor kit's view factory, or the BasicTextUI itself (which implements ViewFactory), if it is null (it always is for JTextField / JTextArea). The BasicTextUI's implementation by default doesn't create views, but returns null. BasicTextFieldUI / BasicTextAreaUI override create() and create the elements as listed below.

To exchange the mappings for JEditorPane/JTextPane, replace the editor kit. For JTextField / JTextArea the mappings can only be done differently by replacing the UI classes.

The root view of a JTextComponent can be accessed by textComponent.getUI().getRootView(textComponent). This implies that the whole view hierarchy is lost and must be recreated when the LAF changes.

Standard mappings

The following mappings usually happen on element name (string comparison) if there is any choice at all.

BasicTextField/AreaUI inspect the document property "i18n" to see if bidirectional layout must be supported. As this may be dynamically changing (and document properties cannot be observed), BasicTextUI tests changes for this property every time its DocumentListener's insertUpdate() has been called and then recreates the views [1]. BasicTextField/AreaUI also test for this change in the component's "font" property change handling.

BasicTextUI also sets the RUN_DIRECTION property on the Document and recreates views if the component orientation changed[2].

BasicTextFieldUI (for JTextField)

without i18n:

Element

View

root element

FieldView

with i18n:

Element name

View

paragraph

subclass of ParagraphView

content

GlyphView

any other

FieldView (not really intented?)

BasicTextAreaUI (for JTextArea)

Views are recreated on "lineWrap" or "wrapStyleWord" property change.

without i18n:

Element

View

root element, with line wrap

WrappedPlainView

root element, no line wrap

PlainView

with i18n:

Element name

View

paragraph

BoxView

content

subclass of ParagraphView, content is displayed by GlyphView

any other

null (usually problematic)

JEditorPane.PlainEditorKit

similar to JTextArea, always uses WrappedPlainView

Problems of these mappings

WrappedPlainView and PlainView (and thus FieldView) require the root element of the Document to have children (the "paragraphs"). This is not documented anywhere(?). That means that JTextField/JTextArea (with Basic LAF or non-changed subclasses) will not display valid Documents properly (those whose root element is a leaf). A method of Utilities (getParagraphElement) also assumes this (even a still more special) structure for non-StyledDocuments.

With the i18n property set, the problems are different but even worse:

StyledEditorKit

Element name

View

section

BoxView

paragraph

ParagraphView

content

LabelView

component

ComponentView

icon

IconView

any other

LabelView

HTML package mappings

HTMLEditorKit bases its views on the NameAttribute (which is HTML.Tag and not a String). It falls back to StyledEditorKit behaviour if not found.


[1] BasicTextUI does this although it has no code specific on the "i18n" property. This may lead to unnecessary recreation of the view hierarchies. BasicTextUI assumes that a) any EditorKit will create its views depending on whether i18n is true and b) that it is not capable of handling changes alone, as it can well be, since it is may explicitly register on the component (and thus track changes of the Document).

[2] I don't think that's clean. A Document should be displayable in multiple text components, even with multiple orientations, at the same time. The paint/layout methods should instead fall back to the component's orientation only if the property isn't set on the model.


(C) 2001-2009 Christian Kaufhold (swing@chka.de)