All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.adobe.xfa.text.TextMarker Maven / Gradle / Ivy

The newest version!
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(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy