com.adobe.xfa.text.TextMarker Maven / Gradle / Ivy
Show all versions of aem-sdk-api Show documentation
package com.adobe.xfa.text;
/**
* @exclude from published api -- Mike Tardif, May 2006.
*
* All marker classes are derivations of class TextMarker. This is a
* base class that provides common functionality.
*
*
* Like other objects that can be inserted into text streams, markers
* are cloned upon insertion. Thus, the client can delete its (sample)
* marker after insertion into the stream.
*
*
* Class TextMarker derives from class Obj so that implementations
* can use virtual methods Type() and IsDerivedFrom() to do basic XTG
* type management with different marker classes.
*
*
* There are a number of virtual methods that derived implementations
* can override. These notify that implementation of events that occur
* during text editing. All have default implementations which
* generally do nothing, or as little as possible. A number of these
* event notifications include index numbers. As such, they account
* for objects in the stream that dont appear in the rendering (for
* example, attribute changes). Therefore, simple math wont work on
* these indexes if the implementation is interested only in characters
* or other units. The implementation must use text position objects
* and type-specific stepping operations to count characters in the
* stream.
*
*
* For more information, please see the specification.
*
*/
public abstract class TextMarker {
/**
* Conditions on which a marker instance should be split.
*
* Some range marker derivations will need to be split into two separate
* markers when insertions occur or around the presence of particular
* content. This enumeration describes that splitting.
*
*
* SPLIT_NONE -The range marker is never automatically split.
*
*
* SPLIT_PARA - The marker is to be split into separate markers around
* paragraph marks.
*
*
* SPLIT_INSERT - The marker is to be split into separate markers on any
* insertion within the marker's range.
*
*
* SPLIT_INSERT_WRAP - The marker is to be split into separate markers
* on any insertion within the marker's range. In addition, the marker
* will be split if word-wrapping causes its range to spread over two or
* more lines.
*
*
* Superficially, a value of SPLIT_PARA may appear to be a
* specialization of SPLIT_INSERT. However, they are mutually exclusive
* settings that have different semantics for certain operations. For
* more information, please see the external specification.
*
*/
public static final int SPLIT_NONE = 0;
public static final int SPLIT_PARA = 1;
public static final int SPLIT_INSERT = 2;
public static final int SPLIT_INSERT_WRAP = 3;
/**
* Reason that a marker is about to be split.
*
* This enumeration is intended primarily for use in the OnSplit()
* call-back described later. Enumeration values have the following
* meanings:
*
*
* SPLIT_REASON_UNKNOWN - This value is for internal purposes and will
* never be passed to the call-back. It should not be used by the
* client.
*
*
* SPLIT_REASON_FORCED - A split was forced by the client.
*
*
* SPLIT_REASON_INSERT_EMBED - An embedded object has been inserted
* within the marker's range.
*
*
* SPLIT_REASON_INSERT_FIELD - A nested field has been inserted within
* the marker's range.
*
*
* SPLIT_REASON_INSERT_PARA_BREAK - A paragraph break has been inserted
* within the marker's range (and the marker has a split state of
* SPLIT_INSERT).
*
*
* SPLIT_REASON_INSERT_TEXT_PLAIN - Plain text has been inserted within
* the marker's range.
*
*
* SPLIT_REASON_INSERT_TEXT_RICH - Potentially rich text has been
* inserted within the marker's range. Note that the two text insertion
* types simply mirror the AXTE API calls. Text passed to a rich text
* API method may be plain.
*
*
* SPLIT_REASON_PARA_MARKER - This marker has a split state of
* SPLIT_PARA and it needs to be split around a paragraph break.
*
*
* SPLIT_REASON_WORD_WRAP - The marker is being split due to a
* word-wrapping operation.
*
*
* Note that split reasons SPLIT_REASON_WORD_WRAP and those starting
* with SPLIT_REASON_INSERT apply to SPLIT_INSERT markers only. They
* are all considered variations on insertion.
*
*/
public static final int SPLIT_REASON_UNKNOWN = -1;
public static final int SPLIT_REASON_FORCED = 0;
public static final int SPLIT_REASON_INSERT_EMBED = 1;
public static final int SPLIT_REASON_INSERT_FIELD = 2;
public static final int SPLIT_REASON_INSERT_PARA_BREAK = 3;
public static final int SPLIT_REASON_INSERT_TEXT_PLAIN = 4;
public static final int SPLIT_REASON_INSERT_TEXT_RICH = 5;
public static final int SPLIT_REASON_PARA_MARKER = 6;
public static final int SPLIT_REASON_WORD_WRAP = 7;
private PosnMarker mpoLocation;
private int meSplitState;
private boolean mbAutoCoalesce;
private boolean mbAutoRemove;
private boolean mbParaMarker;
/**
* Indicate whether this marker is a position marker.
* @return True if this is a position marker; false if it is a range
* marker or not contained in any stream.
*/
public boolean isPositionMarker () {
return (mpoLocation != null) && (mpoLocation.getMate() == null);
}
/**
* Indicate whether this marker is a range marker.
* @return True if this is a range marker; false if it is a position
* marker or not contained in any stream.
*/
public boolean isRangeMarker () {
return (mpoLocation != null) && (mpoLocation.getMate() != null);
}
/**
* Indicate whether this marker can be automatically coalesced with
* others during editing.
* For more information, please see method SetAutoCoalesce().
* @return True if coalescing is allowed for this marker; false if not.
*/
public boolean getAutoCoalesce () {
return mbAutoCoalesce;
}
/**
* Return the current automatic removal state.
* For more information, please see method SetAutoRemove().
* @return True if automatic removal is enabled for this marker; false
* if not.
*/
public boolean getAutoRemove () {
return mbAutoRemove;
}
/**
* Query whether this is a paragraph marker. For more information,
* please see method SetParaMarker().
* For more information, please see method SetParaMarker().
* @return True if this is a paragraph marker; false if not.
*/
public boolean isParaMarker () {
return mbParaMarker;
}
/**
* Return the current split state.
* @return The current split state for this marker. See the description
* of the SplitStateEnum enumeration for more information.
*/
public int getSplitState () {
return meSplitState;
}
/**
* Return the position of this marker in its containing stream.
* This call is valid only for position markers that are contained in
* text streams.
* @return Position of this marker in its containing stream. If the
* marker is not in any stream or is a range marker, the returned
* position will be invalid (i.e., its stream will be null).
*/
public TextPosn getPosition () {
return isPositionMarker() ? mpoLocation : null;
}
/**
* Return the range of this marker representing its span in the
* containing stream.
* This call is valid only for range markers that are contained in text
* streams.
* @return Range of this marker in its containing stream. If the marker
* is not in any stream or is a position marker, the returned range will
* be invalid (i.e., its stream will be null).
*/
public TextRange getRange () {
return new TextRange (mpoLocation.stream(), mpoLocation.index(), mpoLocation.getMate().index());
}
/**
* Remove this marker from the containing stream.
* If the marker is not in a stream, nothing happens. After this call,
* the stream will have released its reference on the marker. If the
* client wishes to hang on to the marker's pointer, it must increase
* the marker's reference countideally when it first copied the pointer.
*/
public void remove () {
TextStream poStream = getStream();
if (poStream == null) {
return;
}
poStream.removeMarker (this, false);
}
/**
* Forces the range marker to be split if it overlaps the given span.
*
*
* This call makes sense only for markers that are within text streams.
* The span is specified as two indexes into the marker's text stream.
* The method behaves in one of five ways, depending on the relationship
* between the span and the marker's range:
*
*
* If the span does not overlap the marker's range, the call is ignored.
*
*
* If the span overlaps the start of the marker's range but not the end,
* the marker's range is truncated at its start to exclude the overlap.
*
*
* If the span overlaps the end of the marker's range but not the start,
* the marker's range is truncated at its end to exclude the overlap.
*
*
* If the span falls completely inside the marker-s range--overlapping
* neither the start nor the end--the marker is split. Upon return,
* this marker will correspond to the portion of its original range
* before the span and the clone will correspond to the portion after.
*
*
* If the span is a (possibly exact) superset of the marker's range, the
* split operation treats the marker in the same way a complete deletion
* of the marker's text would. The marker is removed from the stream
* and possibly deleted.
*
*
* This method will trigger a call on the marker's OnSplit() event
* handler if a true split (fourth bullet above) occurs.
* @param nSplitStart - Indicates the start of the split span. This
* parameter indicates the future end of this marker's range if a true
* split occurs.
* @param nSplitEnd - Indicates the end of the split span. This
* parameter indicates the future end of this marker's range if a true
* split occurs.
* @param eReason - Reason for the split. It is recommended that the
* client not override the default of SPLIT_REASON_FORCED.
* @return New marker instance created if a true split occurred. If
* null, there was no split.
*/
public TextMarker forceSplit (int nSplitStart, int nSplitEnd, int eReason) {
if (! isRangeMarker()) {
return null;
}
TextStream poStream = getStream();
if (poStream == null) {
return null;
}
return poStream.splitMarker (this, nSplitStart, nSplitEnd, eReason);
}
/**
* Coalesce this marker with another one.
*
* Common usage is to coalesce logically adjacent markers, but the
* client may call this method on disjoint markers as well. Upon
* successful return, this markers range is extended to include the
* union of both markers ranges, as well as any intervening content if
* the markers are not contiguous.
*
*
* In order to be coalesced, the following conditions must be met:
*
*
* -
* The two markers refer to the same text stream.
*
* -
* The two markers have the same type, as reported by the Obj::Type()
* virtual method.
*
* -
* Both markers have the same values for auto coalesce, auto removal,
* paragraph state and split state. Note that two markers that disallow
* coalescing can be explicitly coalesced with this method.
*
*
*
* This method will trigger a call on the marker's OnCoalesce() event
* handler if the above conditions are met. The implementation of that
* event handler may prevent the operation from occurring.
*
*
* AXTE dispatches the marker being coalesced with this one, either
* removing it from the stream (if auto-remove is enabled) or shrinking
* it to a zero-length range at the end of the coalesced range.
*
* @param poOther - Pointer to marker to be coalesced with this one.
* @return True if the operation was successful; false if the conditions
* were not met or the marker prevented the operation in the
* OnCoalesce() event handler.
*/
public boolean forceCoalesce (TextMarker poOther) {
if (! canCoalesce (poOther)) {
return false;
}
return getStream().coalesceMarker (this, poOther);
}
/**
* Create a copy of this marker.
* Implemented by the derived class. The created instance must be of
* the same class as this object and a deep copy must be performed.
* @return A pointer to the cloned copy. The copy is owned by AXTE and
* must not be deleted by the client.
*/
abstract public TextMarker cloneMarker ();
/**
* Notifies a range marker that an attribute change overlaps the
* marker's range.
* This method is called before the attribute change is applied. The
* default implementation does nothing.
* @param nStart - Start of the attribute change's range. This range
* overlaps the marker's range by some amount, but it may or may not
* include all of the marker's text.
* @param nEnd - End of the attribute change's range.
* @param poAttr - Pointer to new attributes that are about to be
* applied.
*/
public void onAttributeChange (int nStart, int nEnd, TextAttr poAttr) {
}
/**
* Handle mouse click event in this range marker.
* The derived class can override this method if it needs to know about
* mouse clicks.
* @param oPosition - Position within parent stream where click
* occurred.
* @return True if the derived class handled the click and wishes to
* suppress further click processing. AXTE will call OnClick() for each
* range marker that spans the click position until one returns true.
* If none return true, AXTE will move the caret to the click position.
* The default implementation simply returns false.
*/
public boolean onClick (TextPosnBase oPosition) {
return false;
}
/**
* Notify the marker that it is about to be coalesced with another.
*
* AXTE will call this method on a marker instance as a result of a call
* to ForceCoalesce(). In addition, it will call this method after an
* editing operation has occurred, if all the following conditions are
* met:
*
*
* -
* An editing operation (typically a deletion) has caused this marker to
* become adjacent to the other one, in logical order
*
* -
* This marker comes first in logical text order
*
* -
* Both markers allow automatic coalescing
* virtual method
*
* -
* The conditions outlined in the ForceCoalesce() method are met
*
*
*
* This is a notification only; the marker derivation may need to update
* its own data structures to represent the coalesced result, but AXTE
* updates this marker's range. AXTE also dispatches the adjacent
* marker, either removing it from the stream (if auto-remove is
* enabled) or shrinking it to a zero-length range at the end of the
* coalesced range. Zero-length markers are not eligible for future
* automatic coalescing operations.
*
*
* The marker's implementation can prevent the coalescing from occurring
* through the return value of this notification method.
*
* @param oOther - Adjacent marker to be coalesced with this one.
* @return True if the derived class wants the coalesce operation to
* occur; false to suppress the coalescing of the two markers. The
* default implementation simply returns true.
*/
public boolean onCoalesce (TextMarker oOther) {
return true;
}
/**
* Notifies a range marker that part or all of its content is about to
* be deleted.
* This method is called before the deletion occurs. The default
* implementation does nothing.
* @param nStart - Start of the deletion range. This range overlaps
* the marker's range by some amount, but it may or may not include all
* of the marker's text.
* @param nEnd - End of the deletion range.
*/
public void onDeleteContent (int nStart, int nEnd) {
}
/**
* Notifies the marker that it is about to be removed from its
* containing text stream and deleted.
* This can occur as a result of one of the following conditions:
*
* -
* The marker has automatic removal enabled and a text editing operation
* within the stream has triggered the removal of the marker.
*
* -
* The containing stream is being destroyed.
*
*
* After this call, the stream will have released its reference on the
* marker. If the client wishes to hang on to the marker's pointer, it
* must increase the marker's reference count--ideally when it first
* copied the pointer.
* @param bEditOnly - True if this is an editing operation that is about
* to remove the auto-delete marker. False if the containing stream is
* being deleted.
*/
public void onRemove (boolean bEditOnly) {
}
/**
* Notifies the marker that it is about to be split.
*
*
* AXTE will call this method when splitting a marker with a split state
* of either SPLIT_PARA or SPLIT_INSERT. The term split text
* refers to the text that is not part of either resulting marker after
* the split occurs. For a SPLIT_INSERT marker, the split text one of
* the following:
*
*
* -
* The inserted text if an insertion caused the split
*
* -
* The sub-range of text that gets the new attribute value if an
* attribute change caused the split
*
* -
* An empty span at the line break point if word-wrapping caused the
* split
*
*
*
* For a SPLIT_PARA marker, it is a single paragraph break--even if that
* paragraph break was part of a larger insertion.
*
*
* This method is called after the insertion, but before any splitting
* has occurred. In other words, this marker's range will have been
* expanded by the number of items in the split text. At the time of
* the call, it can be thought of as covering three sub-spans:
*
*
* -
* The portion before the split text
*
* -
* The split text
*
* -
* The portion after the split text
*
*
*
* Parameters to OnSplit() delimit the extent of the split text within
* the larger marker range.
*
*
* The implementation normally creates a new marker instance--much like
* Clone()--and return it to AXTE. The implementation can use the given
* parameters for informational purposes, but it is not responsible for
* adjusting the marker's range or setting the clone's range. AXTE will
* take care of all of that. The default implementation simply calls
* Clone().
*
*
* The marker can prevent the split from occurring by returning a null
* pointer in this method. In such a case, the marker will simply
* remain in its expanded state, spanning the three portions mentioned
* above. Preventing the split should occur only in specialized
* circumstances, for example, a text run can handle the insertion of
* plain text without being split.
*
*
* After OnSplit() returns, AXTE will adjust this marker's range to
* cover the span before the inserted text. It will attach the clone to
* the span after the inserted text. If this is a SPLIT_PARA marker and
* there are multiple paragraph breaks, AXTE will split the original
* marker at the original break. The clone will temporarily cover the
* remainder of the inserted text--including remaining paragraph
* breaks--as well as any text from the original marker that occurs
* after the insertion. AXTE will then iterate on the next paragraph
* break, calling OnSplit() on the clone, and so on.
* @param nSplitStart - Indicates the start of the split text. This
* parameter indicates the future end of this marker's range.
* @param nSplitEnd - Indicates the end of the split text. This
* parameter indicates the future start of the new marker's range.
* @param eReason - Reason the marker is being split. Please see the
* SplitReasonEnum definition above for more information.
* @return New marker instance to use for the portion after the split
* text; null pointer if the marker is not to be split.
*/
public TextMarker onSplit (int nSplitStart, int nSplitEnd, int eReason) {
return cloneMarker();
}
/**
* Notifies the marker that its range has expanded due to an insertion
* and is about to be truncated.
* This is really just an extension of the OnSplit() call-back that
* handles insertions at the start or end of the marker's range. When
* the call is made, the insertion has occurred and the marker's range
* is temporarily expanded to include the inserted text. The marker
* implementation has the choice of letting AXTE truncate the range to
* exclude the inserted text or leave the range extended. The marker
* implementation may want to hang on to the inserted text.
* @param nSplitStart - Indicates the start of the split text.
* @param nSplitEnd - Indicates the End of the split text.
* @param bEnd - True if the range truncation is to occur at the marker
* range end; false if it is to occur at the range start.
* @param eReason - Reason the marker's range is being truncated.
* Please see the TextMarker::SplitReasonEnum definition above for
* more information.
* @return True if the marker's range is to be truncated; false if it is
* to remain including the inserted text.
*/
public boolean onTruncate (int nSplitStart, int nSplitEnd, boolean bEnd, int eReason) {
return true;
}
// proprietary:
PosnMarker getLocation () {
return mpoLocation;
}
void setLocation (PosnMarker poLocation) {
mpoLocation = poLocation;
}
boolean canCoalesce (TextMarker poOther) {
TextStream poStream = getStream();
return (poOther != null)
&& (poStream != null)
&& (poStream == poOther.getStream())
&& (meSplitState == poOther.meSplitState)
&& (mbAutoCoalesce == poOther.mbAutoCoalesce)
&& (mbAutoRemove == poOther.mbAutoRemove)
&& (mbParaMarker == poOther.mbParaMarker);
}
/**
* Create a defult marker.
* Default attribute states for the marker are split state: SPLIT_NONE,
* auto coalesce: FALSE, auto remove: TRUE, and paragraph marker: FALSE.
*/
protected TextMarker () {
mpoLocation = null;
meSplitState = SPLIT_NONE;
mbAutoCoalesce = true;
mbAutoRemove = true;
mbParaMarker = false;
}
/**
* Create a marker with the given parameters.
* @param bAutoCoalesce - Automatic coalescing status for the marker.
* @param bAutoRemove - Automatic removal status for the marker.
* @param bParaMarker - Indicates whether this is to be a paragraph
* marker.
* @param eSplitState - Split state for the marker (see description of
* the enumeration SplitStateEnum).
*/
protected TextMarker (boolean bAutoCoalesce, boolean bAutoRemove, boolean bParaMarker, int eSplitState) {
mpoLocation = null;
meSplitState = eSplitState;
mbAutoCoalesce = bAutoCoalesce;
mbAutoRemove = bAutoRemove;
mbParaMarker = bParaMarker;
}
/**
* Copy constructor.
* Copies all marker properties except for the reference to the text
* stream. In other words, the marker is not initially associated with
* any stream.
* @param oSource - Source marker to copy.
*/
protected TextMarker (TextMarker oSource) {
copyFrom (oSource);
}
/**
* Enable/disable automatic coalescing for this marker.
*
* A marker instance can declare whether the AXTE marker implementation
* should attempt to coalesce it with other markers during text editing.
* In order to be coalesced, the two markers must meet a number of
* conditions, described under marker event handler OnCoalesce(). If
* all the conditions are met and OnCoalesce() returns true, AXTE will
* coalesce the markers. Coalescing occurs in text content.
*
* @param bAutoCoalesce - True if automatic coalescing is to be allowed
* for this marker; false if not.
*/
protected void setAutoCoalesce (boolean bAutoCoalesce) {
mbAutoCoalesce = bAutoCoalesce;
}
/**
* Enable/disable automatic removal for this marker.
*
* It is possible for an unrelated operation to delete content that
* includes this marker. Depending on the purpose of the marker, it may
* or may not make sense to delete the marker. This method allows the
* marker implementation class to state whether automatic removal should
* be enabled or disabled.
*
*
* If automatic removal is disabled for a position marker and it falls
* in a deletion range, it will not be deleted. Instead, it will be
* repositioned at the start of the deletion range, just like a text
* position would be.
*
*
* Any deletion that covers part but not all of the range of a range
* marker will cause the truncation but not the removal of the marker,
* irrespective of its automatic removal setting. If the deletion
* range is a superset of the marker's range, it will be deleted if
* automatic removal is enabled, or collapse to an empty range at the
* start of the deletion if automatic removal is disabled.
*
*
* If this method is never called, the automatic removal flag defaults
* to true.
*
* @param bAutoRemove - True if automatic removal is to be enabled for
* this marker; false if it is to be disabled.
*/
protected void setAutoRemove (boolean bAutoRemove) {
mbAutoRemove = bAutoRemove;
}
/**
* Set the paragraph marker flag.
*
* Some text attributes can span arbitrary text ranges. For example, a
* particular font name change may start in the middle of one paragraph
* and end in another. Other attributes make sense only in the context
* of entire paragraphs. For example, it doesnt make sense to change
* the left margin in the middle of a line, or even at the start of a
* line since it is not known where the line breaks are until the text
* is formatted.
*
*
* Range markers may exhibit either behaviour as well. Some markers
* make sense only in terms of entire paragraphs (e.g., an HTML heading
* level). Others could be used with a finer granularity (e.g.,
* hyperlink).
*
*
* A marker can declare itself to be either a paragraph marker or not.
* Paragraph markers will always be extended as necessary to span
* complete paragraphs. If a marker is not a paragraph marker, it is
* referred to as a character marker.
*
* @param bParaMarker - True if this marker is to be considered a
* paragraph marker; false if it is a character marker. If this method
* is never called for a marker, it defaults to being a character
* marker.
*/
protected void setParaMarker (boolean bParaMarker) {
mbParaMarker = bParaMarker;
}
/**
* Set the split state for this marker.
*
* Note that split states make sense only for range markers. For more
* information, please see the description of the SplitStateEnum
* enumeration.
*
*
* If this method is never called, the split state defaults to
* SPLIT_NONE.
*
* @param eSplitState - New split state for this marker.
*/
protected void setSplitState (int eSplitState) {
meSplitState = eSplitState;
}
/**
* Assignment operator.
* Copies all marker properties except for the reference to the text
* stream. In other words, this marker does not change its stream
* association.
* @param oSource - Source marker to copy.
*/
protected void copyFrom (TextMarker oSource) {
meSplitState = oSource.meSplitState;
mbAutoCoalesce = oSource.mbAutoCoalesce;
mbAutoRemove = oSource.mbAutoRemove;
mbParaMarker = oSource.mbParaMarker;
}
/**
* Get the text stream that this marker is currently associated with.
* @return Pointer to associated stream for this marker; NULL if there
* is no stream association.
*/
protected TextStream getStream () {
return (mpoLocation == null) ? null : mpoLocation.stream();
}
}