These three key methods must be implemented by all concretesubclasses of View: public abstract void paintGraphics g, Shape allocation Lay out and paint the View within the bounds of the
Trang 1Figure 22-11.) For DefaultStyledDocuments in a
JTextPane, the View tree is modeled closely on the structure
of the Element tree, with almost a one-to-one mapping fromElements to Views A PlainDocument in a JTextArea is
handled more simply, with a single View object that paints theentire Element tree
Figure 22-11 View trees created from Element trees
Notice that the View trees have a root View above what could
be considered the "natural" root This was done to ease the
Trang 2DocumentListener, the root View also takes care of
dispatching DocumentEvents to its children The actual type ofthe root View is a package-private inner class (You are free tocreate a View tree with any root you like, so this does not
always need to be the case The implementations of the
TextUI.getRootView( ) method that Swing provides do
return a package-private View class.)
Creation of the View tree is often handled by the text
component's TextUI, but if its EditorKit returns a non-nullvalue from its getViewFactory( ) method, this task is
22.5.1.1 Method
public View create(Element elem)
Return a View for the given Element
22.5.2 The View Class
Trang 3nonrectangular rendering areas, but the existing View classestreat Shape objects as Rectangles You can convert a Shapeinto a Rectangle (int coordinates) by calling
someShape.getBounds( ), or you can convert a Shape into aRectangle2D (float coordinates) by calling
Trang 4An axis value should be either X_AXIS or Y_AXIS (int
constants) View has several indexed properties that expect theindex to be one of these two values (The exception is the viewproperty getView(n) requests the nth child of the View.)
22.5.2.5 Bias
Many View methods have a parameter of type Position.Bias(see the previous discussion) There are only two values for anobject of this type: Bias.Forward and Bias.Backward Theidea is that the addition of a Bias refines a Document offsetsomewhat Without a Bias, if a user clicks to an offset of 5,then you know the click was either on the right half of the 4thcharacter or on the left half of the 5th The Bias parameterdistinguishes between the two cases
That said, Swing's handling of Position.Bias is spotty Manymethod implementations simply ignore the Bias parameter,and many callers blindly pass in Bias.Forward Should youdecide to do the same, you would be in good company
Trang 5attributes AttributeSet · From element
container Container · From parent
document Document · From element
element Element · From constructor
endOffset int · From element
graphics1.3 Graphics ·
maximumSpani float · (resizeWeight<=0 ? preferredSpan :Integer.MAX_VALUE)
minimumSpani float · (resizeWeight<=0 ? preferredSpan :0)
parent View · · null
preferredSpani float · Abstract
resizeWeight i int · 0
startOffset int · From element
viewi View · null
viewCount int · 0
viewFactory ViewFactory · From parent
visible boolean · true
Trang 6i indexed,
1.3 since 1.3
The properties are defined as follows:
attributes
This property defines the AttributeSet used by the View
to render an Element By default, the Element's attributesare used However, View objects should access the
attributes through the getAttributes( ) accessor to
allow View-specific attributes to be added to the Element'sattributes or to allow the attributes to be converted in someway by the View subclasses
container
This property is the Container ultimately responsible forthis View This View uses the container's coordinate
system as its own, without performing any translation forchild Views We refer to this coordinate system as view
coordinates.
element
This property is the Element this View is responsible forrendering The document, startOffset , and endOffsetproperties are taken directly from the element property.viewCount
This property defines the number of children this View has,and the indexed view property gives access to specific
children Typically, only subclasses of CompositeView (plusroot Views) have any children
Trang 7The other four properties help determine the minimum,
maximum, and preferred size of the component using the View.preferredSpan reflects the View's preferred size along a
particular axis resizeWeight is used to determine the
minimum and maximum size of the View A value of 0 (or less)indicates that the view should not be resized The
minimumSpan and maximumSpan of a View with a
resizeWeight of 0 are equal to the preferredSpan
Otherwise (if resizeWeight > 0), the minimumSpan is
considered to be 0 while the maximumSpan is
Integer.MAX_VALUE
Trang 9These three key methods must be implemented by all concretesubclasses of View:
public abstract void paint(Graphics g, Shape allocation)
Lay out and paint the View within the bounds of the givenShape with the given Graphics The allocation may bedifferent than the last time the View was painted, so theView must be prepared to reorganize its layout
appropriately For efficiency, there is usually no clippingregion set on the Graphics object It's the View's
responsibility to stay within the allocation (or explicitly callg.setClip(allocation)) Also, you can't be sure thatthe Graphics object has any other settings (foregroundcolor, background color, etc.)
public abstract Shape modelToView(int offset, Shape allocation, Position.Bias b) throws BadLocationException
Convert from a Document offset to view coordinates Thereturn value should be a small Rectangle (or another
Shape) that designates the region in which the character atthat offset is drawn Be prepared for the Position.Biasargument to be null, in which case it should be treated asPosition.Bias.Forward
public abstract int viewToModel(float x, float y, Shape
allocation, Position.Bias biasReturn[])
Convert from view coordinates to a Document offset Thereturn value should be the Document offset closest to point(x, y) You should set the value of biasReturn[0] to
Trang 10Bias.Forward, you won't be alone, but set it correctly ifyou can.)
In the method descriptions that follow, we describe the
functions of the methods for a generic subclass of View Thesefunctions are not what the methods usually do in the View classitself The View class does provide implementations, but theyare often empty or minimal (i.e., they always return null oralways return this)
22.5.2.10 Translation methods
These methods (with the addition of two of the above abstractmethods) translate between Document offsets and view
coordinates Views use the same coordinate system as the textcomponent in which they are drawn
public Shape modelToView(int p0, Position.Bias b0,int p1,
Position.Bias b1, Shape allocation) throws BadLocationException
Like the abstract modelToView( ) method, but returns aShape that binds a range of characters instead of a singlecharacter (p0 and p1 are Document offsets.)
public int getNextVisualPositionFrom(int offset, PositionBias
bias, Shape a, int direction, Position.Bias[] biasReturn) throws BadLocationException
This method determines where the caret goes when theuser presses one of the arrow keys The direction parameter
is one of SwingConstants.NORTH, SOUTH, EAST, or WEST.The input and output are both Document offsets, so
Trang 11reconverted The View class has a good implementationthat tries to respect magicCaretPosition (if any) andcalls Utilities.getPostionAbove( ) and
getPositionBelow( ) for NORTH and SOUTH You shouldset the value of biasReturn[0] to Bias.Forward or
public int getViewIndex(float x, float y, Shape allocation) throws BadLocationException
Return the index of the child View that corresponds to thegiven point, or -1 if no such child exists This method wasintroduced in SDK 1.4
public String getToolTipText(float x, float y, Shape allocation)
Return the tooltip for the given point, or null if there isnone This method was introduced in SDK 1.4 to supportthe display of ALT text from HTML IMG tags in
Trang 12Ideally, the new View should have a span of length alongthe given axis The pos argument designates the startingposition (along the same axis) for the new View's
allocation Most Views ignore this argument except for
things such as calculating the positions of tab stops Viewsthat support breaking typically implement this by calling thecreateFragment( ) method after determining an offsetfor the far side of the break Views that don't support
breaking return themselves unbroken (via return this)
Suppose we're trying to draw lines of text that are 400
pixels wide and we've already drawn 280 pixels worth oftext on the current line We could call breakView(X_AXIS, offset, 280, 120) in an attempt to fill out the line TheView returned may or may not have the horizontal span weasked for
public int getBreakWeight(int axis, float pos, float length)
Return a "score" indicating how appropriate it would be tobreak this View into a piece with the given length alongthe given axis (from the start of the View, i.e., from theDocument offset designated by its startOffset property).The return value should be one of the constants from Table22-35 The pos argument designates the starting position(along the same axis) of the View's allocation Most Viewsignore this argument except for things such as calculatingthe positions of tab stops
public View createFragment(int p0, int p1)
Return a new View for painting part of this View's content.The new View should cover the Document from offset p0 tooffset p1, which are in the range defined by the View's
Trang 13startOffset and endOffset properties Views that don'tsupport breaking return themselves unbroken (via return this).
22.5.2.12 Tree management methods
These methods (introduced in SDK 1.3) allow the structure ofthe View tree to be modified In Views that don't support
Trang 14method is analogous to invalidate( ) in Component
information for the child should be discarded, and
preferenceChanged( ) should be called on this View'sparent (grandparent of the child) A preferenceChanged( ) on the root View triggers a revalidate( ) on the textcomponent
require an allocation argument So you need the value
returned by this method to call them
Trang 15between them (Note that the View types used by JTextAreaand JTextPane are depicted in Figure 22-11.)
Figure 22-12 View class diagram
Trang 16PlainView
Displays one or more nonwrapped lines of text in a singlefont and color
Trang 17BoxView
A subclass of CompositeView that tiles its child Viewsalong an axis (as when paragraphs are tiled down a page,for example)
An abstract subclass of BoxView that defines a "flow
Trang 18ParagraphView
An subclass of FlowView that knows how to display an
indented paragraph of text that may have a mix of styles.ZoneView
A subclass of BoxView
that attempts to be memory-efficient by deferring the creation of child Views until theyare needed This can be useful for displaying (parts of) verylarge Element trees, but this class is unused in Swing
AsyncBoxView
Behaves like BoxView but performs layout on a low-prioritythread in an attempt to free up the GUI thread for otherthings The thread and pending layout tasks are managed
by the LayoutQueue class
Trang 19FormView <input> , <select> , <textarea> (HTML forms)
ImageView <img>
InlineView Inline text
ListView <ul> , <ol> , <dir> , <menu>
ObjectView Component specified in <object> tag
ParagraphView <p> (including implied <p> tags), <dt> , <h1> , <h2> , <h3> , <h4> , <h5> ,
in your HTML, ObjectView instantiates the Object and (if it is
a Component, including JComponent) renders it with the rest
of the HTML This works for any Object type, but (at least for
now) the <param> tag works only for properties of type
Trang 20Return the next tab stop position after the specified
position Values are expressed in points For example, aView with tab stops every 80 points, starting at 0, wouldreturn 240.0 for an input of 227.0 The second parameter isthe Document offset of the tab, which can be used to look
22.5.5.1 Methods
public abstract float getTabbedSpan( float x, TabExpander e)
Return a value indicating the span of the View, starting atthe specified point and using the supplied TabExpander toexpand tabs
public abstract float getPartialSpan(int p0, int p1)
Return a value indicating the span needed to cover the
range delimited by the specified document offsets
Implementations may assume that there are no tabs in thegiven range
22.5.6 The Utilities Class
This class defines a number of static methods used by the text
Trang 21system are declared to be ints, not floats
22.5.6.1 Public static methods
public static final int getWordStart(JTextComponent c, int
offset) throws BadLocationException
public static final int getWordEnd(JTextComponent c, int offset) throws BadLocationException
Return the Document offset at the beginning (or one
position past the end) of the word at the specified
Document offset
public static final int getPreviousWord(JTextComponent c, int offset) throws BadLocationException
public static final int getNextWord(JTextComponent c, int offset) throws BadLocationException
Return the Document offset at the beginning of the wordthat precedes or follows the specified offset
public static final int getRowStart(JTextComponent c, int offset) throws BadLocationException
public static final int getRowEnd(JTextComponent c, int offset) throws BadLocationException
Return the Document offset corresponding to the start orend of the row containing the specified offset
public static final int getPositionAbove(JTextComponent c, int offset, int x) throws BadLocationException
public static int getPositionBelow(JTextComponent c, int offset, int x) throws BadLocationException
Trang 22public static final Element
getParagraphElement(JTextComponent c, int offset)
Return the paragraph Element corresponding to the
specified Document offset If the component's model is aStyledDocument, it delegates to the model's
getParagraphElement( ) method Otherwise, the
Document's defaultRootElement is queried for the childcontaining the given offset
public static final int getBreakLocation(Segment s, FontMetrics metrics, int x0, int x, TabExpander e, int startOffset)
Try to find a suitable line-break location by looking for
whitespace in the supplied Segment x0 and x (both in viewcoordinates) are the start and intended end of the span.The return value is a Document offset The TabExpandermay be null, but then tabs are counted as spaces
public static final int drawTabbedText(Segment s, int x, int y, Graphics g, TabExpander e, int startOffset)
Draw the Segment's text, starting at startOffset, to thesupplied Graphics at the specified point (x, y) in view
coordinates The TabExpander may be null, but then tabsare counted as spaces The return value is the x-coordinate
at the end of the drawn text
public static final int getTabbedTextWidth(Segment s,
FontMetrics metrics, int x, TabExpander e, int startOffset)
Return the width (in view coordinates) of the Segment'stext, starting at startOffset, with tabs expanded The x
Trang 23FontMetrics metrics, int x0, int x, TabExpander e, int
startOffset, boolean round)
This is the same as the previous method if round is true
If round is false, when x falls between two characters, itreturns the offset of the left one even if the right one is
closer