public class TextBuffer extends Object
TextView
Widget. Together, these
make for a powerful text display and text editing capability, but it does
come at the cost of considerable come complexity.
TextBuffer buffer; buffer = new TextBuffer(); buffer.setText("Hello world!");Of course, you rarely just want to write an entire body of text in one go. To insert text in a more piecemeal fashion we use one of the
insert()
family of methods, but before we can do so, we need
to indicate where we want to insert that text. This is the role of
TextIter
class.
TextIter pointer; pointer = buffer.getIterStart(); buffer.insert(pointer, "This is the beginning");Note that TextIters are not persistent; as soon as any change is made to the TextBuffer all TextIters are invalidated and you'll need to acquire new ones. If you need a stable reference to a particular position in the text, create a TextMark with
createMark()
.
As you might expect, a TextBuffer has a notion of a cursor which indicates the (user's) current insertion point. You can get the TextMark representing the cursor, and can use it to insert text or otherwise manipulate a position by converting it to a valid TextIter:
TextMark cursor; cursor = buffer.getInsert(); ... pointer = cursor.getIter(); buffer.insert(pointer, "This text was inserted at the cursor");The
insertAtCursor()
method is a shortcut for this.
There are an incredibly wide range of methods available on the TextIter
class for manipulating the position into the TextBuffer that it represents
and for finding out more information about the nature of the text at that
point. TextIter's forwardLine()
is one
example; you could use it to count the non-empty lines in a TextBuffer:
int paragraphs; ... pointer = buffer.getIterStart(); paragraphs = 0; while (pointer.forwardLine()) { if (pointer.startsWord()) { paragraphs++; } }Although trivial, this raises a pitfall you need to be aware of: lines of text in a TextBuffer are not the same as wrapped visible lines in a TextView. Lines in a TextBuffer are a sequences of characters separated by newlines (you don't need a
'\n'
at the end of the TextBuffer;
the end is an implicit line termination). When presented in a TextView with
word wrapping enabled, however, each of these lines may take up more than
one line on the screen. The term paragraph is used there; see
forwardDisplayLine()
to move
a TextIter to the next displayed line within a paragraph as shown on screen
in a TextView.
Finally, formatting and other properties can be set on ranges of text. See
TextTag
. While these are mostly about visual presentation, they are
nevertheless set by applying TextTags to text in the TextBuffer via the
applyTag()
and
insert()
methods here.
These APIs can be somewhat frustrating to use as the methods you need (relative to the order you need them in) tend to be scattered around between TextView, TextBuffer, and TextIter. It was tempting to try and normalize these to a common interface, but in the end we deferred to being faithful to the placement of methods in the underlying library's classes. We have done our best to cross reference our documentation to help you find the "next" logical element when you need it, but if you find yourself struggling to find something and think this documentation could benefit from another such pointer, please feel free to suggest it.
Modifier and Type | Class and Description |
---|---|
static interface |
TextBuffer.ApplyTag
The signal emitted when a TextTag is added to a range of text.
|
static interface |
TextBuffer.BeginUserAction
Signal emitted when a "user action" is initiated.
|
static interface |
TextBuffer.Changed
The signal emitted when the contents of the TextBuffer have changed.
|
static interface |
TextBuffer.DeleteRange
Signal emitted when one or more characters are deleted.
|
static interface |
TextBuffer.EndUserAction
The signal emitted when a "user action" stops.
|
static interface |
TextBuffer.InsertText
Signal emitted when text is inserted into the TextBuffer.
|
static interface |
TextBuffer.MarkSet
Signal emitted when a TextMark is set (or moved) in this TextBuffer.
|
static interface |
TextBuffer.NotifyCursorPosition
Signal emitted when the cursor-position property changes.
|
static interface |
TextBuffer.RemoveTag
The signal emitted when a TextTag is removed from a range of text.
|
Modifier and Type | Field and Description |
---|---|
static char |
OBJECT_REPLACEMENT_CHARACTER
This constant is used to identify cells in the TextBuffer that are not
actually characters - in other words, Widgets and Pixbufs.
|
Constructor and Description |
---|
TextBuffer()
Create a new TextBuffer.
|
TextBuffer(TextTagTable tags)
Create a new TextBuffer.
|
Modifier and Type | Method and Description |
---|---|
void |
applyTag(TextTag[] tags,
TextIter start,
TextIter finish)
Apply an array of TextTags to the given range.
|
void |
applyTag(TextTag tag,
TextIter start,
TextIter finish)
Apply the selected tag on the area in the TextBuffer between the start
and finish positions.
|
void |
beginUserAction()
Mark the beginning of a user initiated action.
|
void |
connect(TextBuffer.ApplyTag handler)
Hook up a handler for
TextBuffer.ApplyTag signals on this
TextBuffer. |
void |
connect(TextBuffer.BeginUserAction handler)
Hookup a
TextBuffer.BeginUserAction signal handler. |
void |
connect(TextBuffer.Changed handler)
Hook up a handler for
TextBuffer.Changed signals. |
void |
connect(TextBuffer.DeleteRange handler)
Hook up a handler for
TextBuffer.DeleteRange signals on
this TextBuffer. |
void |
connect(TextBuffer.EndUserAction handler)
Hookup a
TextBuffer.EndUserAction signal handler. |
void |
connect(TextBuffer.InsertText handler)
Hook up a handler for
TextBuffer.InsertText signals. |
void |
connect(TextBuffer.MarkSet handler)
Hook up a handler for
TextBuffer.MarkSet signals on this
TextBuffer. |
void |
connect(TextBuffer.NotifyCursorPosition handler)
Hook up a handler to receive
TextBuffer.NotifyCursorPosition signals emitted when the
cursor-position of this TextBuffer changes. |
void |
connect(TextBuffer.RemoveTag handler)
Hook up a handler for
TextBuffer.RemoveTag signals on this
TextBuffer. |
void |
connectAfter(TextBuffer.InsertText handler)
Hook up a handler for
TextBuffer.InsertText signals that
will be called after the default handler. |
TextMark |
createMark(TextIter where,
boolean gravity)
Create a new TextMark at the position of the supplied TextIter.
|
void |
delete(TextIter start,
TextIter finish)
Delete text between
start and finish . |
void |
deleteInteractive(TextIter start,
TextIter finish,
boolean defaultEditability)
Delete text like
delete() , but only
if the range given is editable. |
void |
endUserAction()
Calls to
endUserAction() close off the matching
beginUserAction() call. |
int |
getCharCount()
Returns the number of characters in this buffer.
|
int |
getCursorPosition()
Get the current value of the cursor-position property.
|
boolean |
getHasSelection()
Returns whether or not the TextBuffer has a selection
|
TextMark |
getInsert()
Returns the current cursor position.
|
TextIter |
getIter(int offset)
Get a TextIter pointing at the position
offset characters
into the TextBuffer. |
TextIter |
getIter(TextMark mark)
|
TextIter |
getIterEnd()
Returns a pointer to the end of the TextBuffer.
|
TextIter |
getIterStart()
Returns a pointer to the beginning of the TextBuffer.
|
int |
getLineCount()
Returns the number of text lines in this buffer.
|
boolean |
getModified()
Find out if the TextBuffer's content has changed.
|
TextMark |
getSelectionBound()
Returns the end of the current selection.
|
String |
getSlice(TextIter start,
TextIter finish,
boolean includeHidden)
Returns the text in the range
start .. |
String |
getText()
Returns the text in the TextBuffer in its entirety.
|
String |
getText(TextIter start,
TextIter finish,
boolean includeHidden)
Returns the text in the range
start .. |
void |
insert(TextIter position,
Pixbuf image)
Inserts an image at the cursor position.
|
void |
insert(TextIter position,
String text)
Insert a text at a given position.
|
void |
insert(TextIter position,
String text,
Collection<TextTag> tags)
Insert text at the given position, applying all of the tags specified.
|
void |
insert(TextIter position,
String text,
TextTag tag)
Insert text as for
insert() but
simultaneously apply the formatting described by tag . |
void |
insert(TextIter position,
String text,
TextTag[] tags)
Insert text at the given position, applying all of the tags specified.
|
void |
insert(TextIter position,
Widget child,
TextView which)
Insert a Widget into the TextBuffer.
|
void |
insertAtCursor(String text)
Insert the text at the current cursor position.
|
void |
insertInteractive(TextIter pos,
String text,
boolean defaultEditability)
Like
insert() , but the insertion will
not occur if pos points to a non-editable location in the
buffer - meaning that it is enclosed in TextTags that mark the area
non-editable. |
void |
moveMark(TextMark mark,
TextIter where)
Manually move a TextMark to a new location.
|
void |
placeCursor(TextIter location)
Move the cursor (ie, the selection-bound and
insert marks) to the given location.
|
void |
removeAllTags(TextIter start,
TextIter finish)
Remove all TextTags that may be present in a range.
|
void |
removeTag(TextTag tag,
TextIter start,
TextIter finish)
Remove the effect of the supplied
tag from across the
range between start and end . |
void |
selectRange(TextIter start,
TextIter finish)
Select a range of text.
|
void |
setModified(boolean modified)
Marks the content as changed.
|
void |
setText(String text)
Replace the entire current contents of the TextBuffer.
|
void |
stopDeleteRange()
Tell a currently active
TextBuffer.DeleteRange signal
emission to stop. |
void |
stopInsertText()
Tell a currently active
TextBuffer.InsertText signal
emission to stop. |
public static final char OBJECT_REPLACEMENT_CHARACTER
0xFFFC
, the "Object
Replacement Character" from the Special block. You might see it as
 in other contexts.public TextBuffer()
This will use the default built-in TextTagTable (shared by all
TextBuffers constructed with this call) which in turn will be populated
with tags created using the no-arg TextTag
constructor. This is a convenience; if you need to segregate TextTags
used by different TextBuffers then just use the other TextBuffer
constructor.
public TextBuffer(TextTagTable tags)
public void applyTag(TextTag[] tags, TextIter start, TextIter finish)
public void applyTag(TextTag tag, TextIter start, TextIter finish)
public void beginUserAction()
beginUserAction()
can nest, but they need to be paired
with calls to endUserAction()
. The outer-most
call to this method will raise TextBuffer.BeginUserAction
.
Note that user input into a TextView that is handled by GTK's default
Widget.KeyPressEvent
handler will likewise begin a user
action sequence.public void connect(TextBuffer.ApplyTag handler)
TextBuffer.ApplyTag
signals on this
TextBuffer.public void connect(TextBuffer.BeginUserAction handler)
TextBuffer.BeginUserAction
signal handler.public void connect(TextBuffer.Changed handler)
TextBuffer.Changed
signals.public void connect(TextBuffer.DeleteRange handler)
TextBuffer.DeleteRange
signals on
this TextBuffer.public void connect(TextBuffer.EndUserAction handler)
TextBuffer.EndUserAction
signal handler.public void connect(TextBuffer.InsertText handler)
TextBuffer.InsertText
signals. This
will be invoked before the default handler is run, that is, before the
new text is actually inserted into the TextBuffer.public void connect(TextBuffer.MarkSet handler)
TextBuffer.MarkSet
signals on this
TextBuffer.public void connect(TextBuffer.NotifyCursorPosition handler)
TextBuffer.NotifyCursorPosition
signals emitted when the
cursor-position of this TextBuffer changes.public void connect(TextBuffer.RemoveTag handler)
TextBuffer.RemoveTag
signals on this
TextBuffer.public void connectAfter(TextBuffer.InsertText handler)
TextBuffer.InsertText
signals that
will be called after the default handler.public TextMark createMark(TextIter where, boolean gravity)
The gravity
parameter is interesting. It specifies whether
you want the TextMark to have left-gravity. If LEFT
(true
), then the TextMark will remain pointing to
the same location if text is inserted at this point. If
RIGHT
(false
), then as text is
inserted at this point the TextMark will move to the right. The
standard behaviour of the blinking cursor we all stare at all day long
following us as we type is an example of right-gravity.
public void delete(TextIter start, TextIter finish)
start
and finish
. (The
order of the two TextIters doesn't matter; this method will delete
between the two regardless).
The two TextIters passed to delete()
will be reset so as
to point to the location where the text was removed. This can be a
useful feature; since it mutates the TextBuffer, calling this method
will invalidate all other TextIters.
public void deleteInteractive(TextIter start, TextIter finish, boolean defaultEditability)
delete()
, but only
if the range given is editable.
See insertInteractive()
for a discussion of the
defaultEditability
parameter.
This method is conducted as a user action, so the
TextBuffer.BeginUserAction
and
TextBuffer.EndUserAction
signals will be raised before and
after carrying out the deletion.
public void endUserAction()
endUserAction()
close off the matching
beginUserAction()
call.
TextBuffer.EndUserAction
will only be emitted when the
outer most user action is closed.public int getCharCount()
public int getCursorPosition()
This corresponds to the offset of the insert TextMark; if
you already have a TextIter for that you call it's
getOffset()
instead.
public boolean getHasSelection()
public TextMark getInsert()
You can call getIter()
to convert the
insert TextMark to an TextIter.
public TextIter getIter(int offset)
offset
characters
into the TextBuffer.public TextIter getIter(TextMark mark)
TextMark
into a valid TextIter
that you can use to point into the TextBuffer in its current
state.public TextIter getIterEnd()
public TextIter getIterStart()
public int getLineCount()
public boolean getModified()
setModified(false)
"; operations which
change the TextBuffer will toggle this property, and you can of course
manually set it with setModified(true)
.
This can be used to record whether a file being edited has been modified and is not yet saved to disk (although most applications would probably track that state more robustly, this can at least feed information into that process).
public TextMark getSelectionBound()
getInsert()
.
Under ordinary circumstances you could think the selection-bound TextMark as being the beginning of a selection, and the insert mark as the end, but if the user (or you, programmatically) has selected "backwards" then this TextMark will be further ahead in the TextBuffer than the insertion one.
You can call getIter()
to convert the
TextMark to an TextIter.
public String getSlice(TextIter start, TextIter finish, boolean includeHidden)
start
.. finish
with the OBJECT_REPLACEMENT_CHARACTER
marking any positions
that are actually anchors for Widgets or Images.
Compare to getText()
,
which skips over those meta positions.
public String getText()
getText(TextIter, TextIter, boolean)
from buffer start to end
with includeHidden
being true
.public String getText(TextIter start, TextIter finish, boolean includeHidden)
start
.. finish
. Excludes undisplayed text (text marked with tags that set the
invisibility attribute) if includeHidden
is
false
. Does not include characters representing embedded
images, so indexes into the returned string do not correspond to
indexes into the TextBuffer.public void insert(TextIter position, Pixbuf image)
public void insert(TextIter position, String text)
TextIter
behind the
position move accordingly, while marks keep their position.public void insert(TextIter position, String text, Collection<TextTag> tags)
Having an overload taking a generic is somewhat unusual in java-gnome, but people maintain a (fairly rapidly changing) List or Set with the TextTags they are currently inserting so frequently that we wanted to support this use case efficiently.
public void insert(TextIter position, String text, TextTag tag)
insert()
but
simultaneously apply the formatting described by tag
. You
can specify null
TextTag if you actually want to skip
applying formatting, but in that case you'd probably rather just use
insert()
.public void insert(TextIter position, String text, TextTag[] tags)
public void insert(TextIter position, Widget child, TextView which)
Since multiple TextViews can present information from a given
TextBuffer, you need to specify which
TextView you want
the image to appear in.
Don't forget to show()
the Widget.
Widgets, of course, are neither text nor image data; they need to
appear in a Container hierarchy. Thus adding a Widget is actually a
function of TextView. All the other methods that conceptually insert
things into a TextBuffer are here, however, so we include this as a
convenience. This is just a wrapper around TextView's
add()
.
public void insertAtCursor(String text)
public void insertInteractive(TextIter pos, String text, boolean defaultEditability)
insert()
, but the insertion will
not occur if pos
points to a non-editable location in the
buffer - meaning that it is enclosed in TextTags that mark the area
non-editable.
This method is conducted as a user action, so the
TextBuffer.BeginUserAction
and
TextBuffer.EndUserAction
signals will be raised before and
after carrying out the insertion, respectively.
pos
- Position to insert at.text
- Text to insert.defaultEditability
- How shall the area be handled, if there are no tags
affecting the editable property at the given
location. You probably want to use true
unless
you used TextView's setEditable()
to change the default setting in the display
Widget you're using.public void moveMark(TextMark mark, TextIter where)
Note that if you're trying to move the "cursor", then you are much
better off calling placeCursor()
as that
simultaneously moves both the selection-bound TextMark as
well as the insert one.
public void placeCursor(TextIter location)
This is more than just a convenience function; like
selectRange()
it carries out
the move without intermediate state of part of the text being selected
while the individual TextMarks are being moved.
See also TextView's placeCursorOnscreen()
if you just want to force the cursor into the
currently showing section of the text.
public void removeAllTags(TextIter start, TextIter finish)
Beware that all tags between start
and
end
will be nuked, not just ones set by the piece of code
you happen to be working in. That should be obvious, but apparently
people often make mistakes with this.
public void removeTag(TextTag tag, TextIter start, TextIter finish)
tag
from across the
range between start
and end
. The order of the
two TextIters doesn't actually matter; they are just bounds.public void selectRange(TextIter start, TextIter finish)
start
, and the insert mark will be
placed at end
.
Note that this should be used in preference to manually manipulating
the two marks with moveMark()
calls; doing it that
way results in transient selections appearing which are different than
what you wish to see.
See placeCursor()
if you just want to
move the two marks to the same location; and, assuming the TextBuffer
is showing in a TextView, this will move the cursor.
The native GTK function has these arguments reversed but start and finish make more sense in consecutive order.
public void setModified(boolean modified)
false
. See getModified()
for details.public void setText(String text)
public void stopDeleteRange()
TextBuffer.DeleteRange
signal
emission to stop.public void stopInsertText()
TextBuffer.InsertText
signal
emission to stop.
Calling this only makes sense within the scope of a normal handler of that signal; the effect is to prevent insertion by GTK's default handler.