public class TextView extends Container
TextBuffer
supplying the underlying data model.
TextView can be used for passive display of multiple lines of text by disabling the editable property. Usually, however, a text canvas is used for entering or editing text and the TextView/TextBuffer APIs combine to provide a powerful editing capability.
TextBuffer buffer; TextView view; ScrolledWindow scroll; ... view = new TextView(buffer);Most people want the text to wrap. This is enabled by setting a WrapMode but something must act to restrain the horizontal width of the TextView Widget as it will size-request as much space as would be needed to render a single line. Likewise, wrapping is usually combined with scrolling, and this can be set up in a fairly straight forward fashion:
view.setWrapMode(WrapMode.WORD); scroll = new ScrolledWindow(); scroll.setPolicy(PolicyType.NEVER, PolicyType.ALWAYS); scroll.add(view); ... window.setDefaultSize(300, 700);then packing the ScrolledWindow into a parent Container hierarchy. In example shown here the call to
setDefaultSize()
on the
toplevel would constrain the overall Window size, forcing a narrow
size-allocation on the TextView.
As with TextBuffer, TextIters are the mechanism used to point to locations
within the displayed text. There are numerous methods here on TextView
which manipulate the displayed view (for example
scrollTo()
) many of which take a TextIter as an
indicator of position. Don't be confused that the TextIters are somehow
different depending on their source; they always refer to a position
in a TextBuffer but are often translated to also identify a screen position
in the TextView. You will often find yourself getting a TextIter from the
TextBuffer (perhaps in response to a TextBuffer.Changed
or
TextBuffer.InsertText
emission) and then switching over to
here and calling TextView methods - and then going back to TextBuffer again
a moment later.
TextTag
s are what are use to cause ranges of text within a TextView
to appear with various formatting (bold, italics, colour, etc) over and
above being displayed as normal text. You apply such tags to the TextBuffer
either when insert()
ing or with applyTag()
. See
TextTag for details and examples.
Incidentally, if you need to change the font of the text being rendered in
this TextView by default use Widget's modifyFont()
, for example:
desc = new FontDescription("Monospace, 12"); view.modifyFont(desc);see FontDescription for all the gory details. As usual, we recommend that you do not do this without good cause, instead leaving the application font to be what the user has selected the system Appearance Preferences font settings dialog provided by GNOME.
Working out the heights for each line of text in the TextView and doing related positioning can, at times, be computationally intensive. So GTK does this in a background idle task.
Ordinarily you don't have to worry about this, but methods like
getLineY()
will not report correct information
until this has happened. If you are doing drawing based on the co-ordinates
of a given line in the TEXT
Window of the TextView, it is easy
to be trapped by this: you hook up to the TextBuffer.Changed
thinking that you can use this as an indication of when the TextView has
changed, but unfortunately this turns out not to be the case.
TextBuffer.Changed
is indeed emitted, but the information
returned by getLineY()
will not have been updated until after
the current signal handlers finish and the high-priority idle task can run.
Studying the internal implementation of this logic in GTK, it turns out
that the bulk of the work to do validation of the line height calculations
and text placement happens in code paths triggered off of
Adjustment.ValueChanged
(which is emitted, for example, when
scrolling occurs). Thus there does seem to be a way to trick the TreeView
into getting on with the revalidation early, and that is to emit
Adjustment.ValueChanged
yourself. So, given the usual
TextView/TextBuffer fields and an Adjustment:
... final TextView view; final TextBuffer buffer; final ScrolledWindow scroll; final Adjustment vadj; ...and assuming
view
has been packed into scroll
,
etc, you can get the Adjustment and use it changing as the trigger
to do your redrawing logic:
vadj = scroll.getVAdjustment(); vadj.connect(new Adjustment.ValueChanged() { public void onValueChanged(Adjustment source) { // now the line heights will be correct doSomethingWith(view.getLineY()); } });That works for when real scrolling happens, but if you need to precipitate matters, use Adjustment's
emitValueChanged()
to fire the
Adjustment.ValueChanged
signal:
buffer.connect(new TextBuffer.Changed() { public void onChanged(TextBuffer source) { vadj.emitValueChanged(); } }); window.connect(new Window.ConfigureEvent() { public boolean onConfigureEvent(Widget source, EventConfigure event) { vadj.emitValueChanged(); return false; } });and so on.
A possible alternative to the above workaround is to iterate the main loop;
See Gtk.mainIterationDo()
.
Obviously "internal to GTK" implies that we are second guessing the implementation details. This workaround is not based on documented public behaviour, and unfortunately is not guaranteed to be stable. So as we say in Open Source, Your Mileage May Vary. Perhaps GTK will improve this aspect of the library in the future.
view.attachSpell()The given code will determine the spellchecker language based on
LANG
environment variable and fall back to English if it
can't.Modifier and Type | Class and Description |
---|---|
static interface |
TextView.PopulatePopup
Signal emitted by GTK allowing you to populate MenuItems into the popup
context menu displayed by a TextView (typically in response to the user
right-clicking).
|
Widget.ButtonPressEvent, Widget.ButtonReleaseEvent, Widget.Destroy, Widget.Draw, Widget.EnterNotifyEvent, Widget.FocusInEvent, Widget.FocusOutEvent, Widget.Hide, Widget.KeyPressEvent, Widget.KeyReleaseEvent, Widget.LeaveNotifyEvent, Widget.MapEvent, Widget.MotionNotifyEvent, Widget.PopupMenu, Widget.QueryTooltip, Widget.ScrollEvent, Widget.SizeAllocate, Widget.UnmapEvent, Widget.VisibilityNotifyEvent
Constructor and Description |
---|
TextView()
Create an empty TextView without (yet) having an associated TextBuffer.
|
TextView(TextBuffer buffer)
Create a TextView and display the contents of the TextBuffer.
|
Modifier and Type | Method and Description |
---|---|
void |
add(Widget child,
TextIter position)
Load a Widget into the TextView at the given position.
|
void |
add(Widget child,
TextWindowType which,
int x,
int y)
Place a child Widget into one of the optional side panels around a
TextView.
|
void |
attachSpell()
Create and attach a
Spell object to the view to add
spellchecking capability. |
void |
attachSpell(String lang)
Create and attach a
Spell object to the view to add
spellchecking capability in the given language. |
void |
connect(TextView.PopulatePopup handler)
Hook up a handler to receive
TextView.PopulatePopup
signals on this TextView. |
int |
convertBufferToWindowCoordsX(TextWindowType which,
int X)
Convert
X from buffer co-ordinates to
window co-ordinates. |
int |
convertBufferToWindowCoordsY(TextWindowType which,
int Y)
The canvas that is used to present the text in a TextView has an origin
at
0 ,0 that is at the top left corner. and
extends for as many pixels as would be necessary to present the entire
TextBuffer if it were shown on an arbitrarily large screen without
scrolling. |
int |
convertWindowToBufferCoordsX(TextWindowType which,
int x)
Convert a horizontal position from window co-ordinates (the
on screen position) to buffer co-ordinates (the pixel
distance into the canvas used to describe the entire text being
displayed).
|
int |
convertWindowToBufferCoordsY(TextWindowType which,
int y)
Convert a vertical position from window co-ordinates to
buffer co-ordinates.
|
TextBuffer |
getBuffer()
Get the TextBuffer currently underlying this TextView.
|
boolean |
getCursorVisible()
Returns whether the cursor is currently visible or not.
|
boolean |
getEditable()
Get whether the default editability of the TextView.
|
TextIter |
getIterAtLocation(int X,
int Y)
Get a TextIter corresponding to a given location in the canvas that is
displayed by the TextView.
|
int |
getLineRange(TextIter position)
This is the compliment of
getLineY() ,
giving you the corresponding line height that drops from the top
specified by that method. |
int |
getLineY(TextIter position)
Get the y co-ordinate of the line holding the supplied position.
|
Rectangle |
getLocation(TextIter pointer)
Get a Rectangle enclosing the screen position of the given TreeIter.
|
org.gnome.gtk.Spell |
getSpell()
Get the Spell helper object attached to the view.
|
Rectangle |
getVisibleRectangle()
Get the Rectangle describing what portion of the text canvas the
viewport is currently showing.
|
Window |
getWindow(TextWindowType which)
Get the underlying resource corresponding with one of the sub elements
of this TextView.
|
WrapMode |
getWrapMode()
Get the line wrapping for the view.
|
void |
moveChild(Widget child,
int x,
int y)
Change the co-ordinates of a child Widget in one of the optional side
panels.
|
void |
placeCursorOnscreen()
Move the cursor (ie, the insert TextMark in the current
source TextBuffer) so that is is showing somewhere in the section of
text currently displayed in the viewport.
|
void |
scrollTo(TextIter pointer)
Scroll the viewport so that
pointer is visible. |
void |
scrollTo(TextIter pointer,
double withinMargin,
double xalign,
double yalign)
Scroll the viewport so that
pointer is visible, attempting
to fine tune the result of the scrolling. |
void |
scrollTo(TextMark mark)
Scroll the viewport so that
mark is visible. |
void |
scrollTo(TextMark mark,
double withinMargin,
double xalign,
double yalign)
Scroll the viewport so that
mark is visible. |
void |
setAcceptsTab(boolean setting)
Set the behaviour when the
Tab key is pressed. |
void |
setBorderWindowSize(TextWindowType which,
int size)
Set the size (width for LEFT and RIGHT and height for TOP and BOTTOM)
of the specified side panels.
|
void |
setBuffer(TextBuffer buffer)
Set or replace the TextBuffer that is currently being displayed by this
TextView.
|
void |
setCursorVisible(boolean visible)
Allows you to activate or deactivate the visible cursor.
|
void |
setEditable(boolean editable)
Set whether the normal state of this TextView is to allow editing or
not.
|
void |
setJustify(Justification setting)
Tell this TextView to adopt the given justification.
|
void |
setMarginLeft(int pixels)
Set the padding to appear on the left side of the text.
|
void |
setMarginRight(int pixels)
Set the padding to appear on the right side of the text.
|
void |
setPaddingAboveParagraph(int pixels)
Set the padding that will be put above each paragraph of text in the
TextView.
|
void |
setPaddingBelowParagraph(int pixels)
Set the padding that will be put below each paragraph of text in the
TextView.
|
void |
setPaddingInsideParagraph(int pixels)
Set the padding that will be put between each line in a paragraph if
wrapping is turned on.
|
void |
setWrapMode(WrapMode mode)
Set the line wrapping for the view.
|
add, getChildren, remove, setBorderWidth
activate, addEvents, connect, connect, connect, connect, connect, connect, connect, connect, connect, connect, connect, connect, connect, connect, connect, connect, connect, connect, connect, destroy, getAllocatedHeight, getAllocatedWidth, getAllocation, getCanDefault, getCanFocus, getHasFocus, getName, getParent, getPreferredHeightForWidthMinimum, getPreferredHeightForWidthNatural, getPreferredHeightMinimum, getPreferredHeightNatural, getPreferredWidthForHeightMinimum, getPreferredWidthForHeightNatural, getPreferredWidthMinimum, getPreferredWidthNatural, getRequestMode, getRequisition, getSensitive, getStyleContext, getToplevel, getWindow, grabAdd, grabDefault, grabFocus, grabRemove, hide, isSensitive, overrideBackground, overrideColor, overrideFont, queueDraw, queueDrawArea, realize, setAlignHorizontal, setAlignVertical, setCanDefault, setCanFocus, setEvents, setExpandHorizontal, setExpandVertical, setName, setSensitive, setSizeRequest, setTooltipMarkup, setTooltipText, show, showAll
public TextView()
setBuffer()
to indicate later which
TextBuffer to use.public TextView(TextBuffer buffer)
public void add(Widget child, TextIter position)
A very impressive feature of TextViews is that you can embed Widgets
into them! You supply the position
where you want the
Widget to be anchored, and the Widget will appear in the display amidst
the rest of your text. Don't forget to show()
the Widget
you're adding or it won't appear.
There is an insert()
method available on TextBuffer which wraps this; you may find
it more convenient.
The underlying library is somewhat convoluted about this due to the fact that more than one TextView can be displaying a given TextBuffer, but a Widget can only appear in one parent Container. GTK uses an intermediate called TextChildAnchor to bridge between TextView and TextBuffer; we take care of handling that for you.
public void add(Widget child, TextWindowType which, int x, int y)
TextWindowType
for a
full discussion.
The Widget child
will be placed at the coordinates
x
,y
in the [org.gnome.gdk] Window specified
by which. You can get that Window by calling TextView's variant of
getWindow()
.
This cannot be used unless which
has been initialized to
have a non-zero size with
setBorderWindowSize()
.
WARNING
This feature seems somewhat poorly implemented in
the underlying library. While we have fully exposed it, testing showed
it to be rather difficult to use reliably. Sorry we can't do better for
you.
public void attachSpell()
Spell
object to the view to add
spellchecking capability.
The language is chosen based on the value of LANG
environment variable.
public void attachSpell(String lang)
Spell
object to the view to add
spellchecking capability in the given language.
You're probably just as well to call attachSpell()
and accept the default.
public void connect(TextView.PopulatePopup handler)
TextView.PopulatePopup
signals on this TextView. This will be emitted each time the user
right-clicks or presses the Menu
key, and allows
you to populate the popup menu according to the current circumstances -
in other words, making it a context menu.public int convertBufferToWindowCoordsX(TextWindowType which, int X)
X
from buffer co-ordinates to
window co-ordinates. See
convertBufferToWindowCoordsY()
for a detailed discussion.public int convertBufferToWindowCoordsY(TextWindowType which, int Y)
0
,0
that is at the top left corner. and
extends for as many pixels as would be necessary to present the entire
TextBuffer if it were shown on an arbitrarily large screen without
scrolling.
In most cases, the text shown will require an area larger than the viewport provided by the primary area of the TextView. Even without scrollbars (which can be added by putting the TextView into a ScrolledWindow), the viewport showing the text will slide when the cursor is moved down from the start position and into the body of text. Thus you can be at a position in buffer co-ordinates that is far "greater" than the size of the [org.gnome.gdk] Window that displays it.
Numerous methods, notably getLineY()
,
return a value in buffer co-ordinates. If you need to
determine what position this represents on screen, you need to convert
to window co-ordinates which are relative to the top left
corner of the [org.gnome.gdk] Window being used to present the text on
screen. This method will carry out that conversion for the vertical
axis. See convertBufferToWindowCoordsX()
for the corresponding horizontal
conversion.
public int convertWindowToBufferCoordsX(TextWindowType which, int x)
convertBufferToWindowCoordsY()
for a detailed discussion.public int convertWindowToBufferCoordsY(TextWindowType which, int y)
convertBufferToWindowCoordsY()
for a detailed discussion.public TextBuffer getBuffer()
public boolean getCursorVisible()
public boolean getEditable()
public TextIter getIterAtLocation(int X, int Y)
X
,Y
are in
buffer co-ordinates; if you have a position into the
[org.gnome.gdk] Window then use
convertWindowToBufferCoordsY()
to convert.public int getLineRange(TextIter position)
getLineY()
,
giving you the corresponding line height that drops from the top
specified by that method.
WARNING
Line height values are cached by are not immediately refreshed when the
underlying TextBuffer changes; see the comment titled "Line Height Calculations" in the documentation for
this class for discussion of when you can safely use this method.
public int getLineY(TextIter position)
getLineRange()
.
WARNING
The co-ordinates of the start of each line height are cached are not
immediately updated when the underlying TextBuffer changes; see the
comment titled "Line Height Calculations" in the
documentation for this class for discussion of when you can safely use
this method.
public Rectangle getLocation(TextIter pointer)
This is very useful in a TextBuffer.NotifyCursorPosition
if you need to figure out where the cursor is so as to handle
presentation of some external control accordingly.
public org.gnome.gtk.Spell getSpell()
Reasons you might need to use this are if you have to programatically
change the language being used to spell check against with Spell's
setLanguage()
, or to force the
checker to run again with its recheckAll()
.
You probably won't ever need either.
Obviously there isn't much point in asking for the Spell helper object
if you haven't called attachSpell()
to create
one yet.
public Rectangle getVisibleRectangle()
If you consider the text being displayed as a canvas of a fixed size,
but have turned on scrolling and only have a limited portion of that
canvas displayed due to the Widget being sized smaller than that
canvas, then the x
,y
co-ordinates returned in
the Rectangle represent the current offset into that canvas that
the viewport is showing.
If, for example, you only have vertical scrolling enabled,
view.setWrapMode(WORD); scroll = new ScrolledWindow(); scroll.setPolicy(NEVER, ALWAYS); scroll.add(view);then you can expect
getVisibleRectangle()
to always return
Rectangles with an x
offset value of
0
- the viewport is never scrolled horizontally into the
text canvas.
The width
and height
will, more or less,
correspond to the size of the area of text actually being displayed in
the TextView.
See getLocation()
if you need a
Rectangle enclosing a given TextIter.
public Window getWindow(TextWindowType which)
TextWindowType
for a detailed discussion.public WrapMode getWrapMode()
public void moveChild(Widget child, int x, int y)
x
,y
are specified in window
co-ordinates.public void placeCursorOnscreen()
public void scrollTo(TextIter pointer)
pointer
is visible. This will
get the location specified onto the screen with as little scroll
movement as possible. If you need finer grained control, use one of the
other scrollTo()
variants. variant.public void scrollTo(TextIter pointer, double withinMargin, double xalign, double yalign)
pointer
is visible, attempting
to fine tune the result of the scrolling. See the
scrollTo()
method
taking a TextMark and the same parameters for a detailed discussion of
their use.public void scrollTo(TextMark mark)
mark
is visible. This will
have the effect of doing the minimum necessary scrolling to get the
location specified by the TextMark onto the screen.
See also the full scrollTo()
which takes additional parameters which may allow you to
fine tune the result of the scrolling.
public void scrollTo(TextMark mark, double withinMargin, double xalign, double yalign)
mark
is visible.
The GTK documentation states that the the effective screen will be
reduced by withinMargin
. The acceptable range is
0.0
to 0.5
. TODO It would be cool if someone
could figure out what that actually means; the allowed range is clearly
not a multiplier, so what is it?
The alignment parameters have the same meaning as elsewhere in GTK:
0.0
for top|right, 1.0
for bottom|left.
If you don't need to mess with margins or alignment, then just use the
single arg scrollTo()
method.
WARNING
It turns out that much of TextView's processing is done in idle
callbacks. In particular, this method only works correctly if the
heights of each line have been computed and cached. Since doing so can
be computationally expensive, it happens some time after text is
actually inserted and thus may not be available yet. In theory the
scrolling will be queued up, but you may notice odd effects.
This problem can crop up if you have newly populated a large amount of
text into a TextView and want to force the viewport and cursor to be at
the end of the text. One possible workaround: after doing the large
insertAtCursor()
, you might try the following:
start = buffer.getIterStart(); buffer.placeCursor(start);before calling
end = buffer.getIterEnd(); view.scrollTo(end);this may have the effect of causing the heights to be calculated.
public void setAcceptsTab(boolean setting)
Tab
key is pressed. The
default is true
, that a '\t'
character will
be inserted into the underlying TextBuffer. If you would rather that
Tab
causes the focus to change to the next Widget
rather than inserting a tab, then set this to false
.public void setBorderWindowSize(TextWindowType which, int size)
TextWindowType
. If you're reading this and wanting to set
the padding around the TextView, you probably want
setBorderWidth()
, a method inherited from
Container.public void setBuffer(TextBuffer buffer)
public void setCursorVisible(boolean visible)
true
, indicating the cursor will be shown.public void setEditable(boolean editable)
true
.
Regardless of the default setting here, you can override this for
specific regions of text with by applying TextTags with
setEditable()
set.
public void setJustify(Justification setting)
public void setMarginLeft(int pixels)
0
.
This sets the left-margin property in GTK.
public void setMarginRight(int pixels)
0
.
This sets the right-margin property in GTK.
public void setPaddingAboveParagraph(int pixels)
0
; if you change this then the
first line will be offset from the top edge of the TextView.
See also setPaddingBelowParagraph()
and setPaddingInsideParagraph()
.
This sets the pixels-above-lines property in GTK.
public void setPaddingBelowParagraph(int pixels)
0
, ie for it just to continue
with normal line spacing as specified by the current font metrics.
See also setPaddingAboveParagraph()
and setPaddingInsideParagraph()
.
This sets the pixels-below-lines property in GTK.
public void setPaddingInsideParagraph(int pixels)
setWrapMode()
along with something
acting to restrict the width allocated to the TextView (for example, by
placing it in a ScrolledWindow). When wrapping occurs, then a single
line of text in a TextBuffer will become a paragraph of multiple lines
in the TextView displaying it.
The default is 0
, ie to leave the line spacing alone. If
nothing is causing lines to wrap then this setting will have no effect.
See also setPaddingAboveParagraph()
and setPaddingBelowParagraph()
for the spacing before and after each
paragraph (wrapped or not).
This sets the pixels-inside-wrap property in GTK.
public void setWrapMode(WrapMode mode)