AuthorEditorAccess' select

Questions about XML that are not covered by the other forums should go here.
vanchev
Posts: 4
Joined: Mon Dec 14, 2009 8:37 pm

AuthorEditorAccess' select

Post by vanchev » Mon Jan 18, 2010 8:27 pm

Hello,
I have a question regarding the exact behaviour of the AuthorEditorAccess' select function. In the documentation of the api i can only find this:
select

void select(int startOffset,
int endOffset)

Select the interval between start and end offset.

Parameters:
startOffset - Inclusive start offset
endOffset - Exclusive end offset
For the purposes of my programme i want to place some tags around some untagged elements (well at least not with the new tags). There are many such tags that are to be placed and it is difficult to place everything automatically, so a supervision from the user is required. This being said i want to jump in the text right to the next occurrence of some word(or words), that i are possible candidates for tagging. With each jump the selection should change and a question box should ask if the user really wants this element tagged with a current tag. I think this should be done with the select function, so i am using it. However i find that the function does not use the actual position of the element in the text, but rather uses some kind of alters numbering. My question is exactly how this numbering works. I have discovered that some whole tags are being counted as 1 position and some not (in my observation the first 2 tags are being counted for 5x positions and all latter tags for just one - since i was not thorough with my analysis with the text i don't know if this is actually so). I would appreciate some heads up.

With Best Regards
Vanchev

P.S. I am using <oXygen/> as an Eclipse plugin. The OS is Windows and the version is 10.3.

Radu
Posts: 7028
Joined: Fri Jul 09, 2004 5:18 pm

Re: AuthorEditorAccess' select

Post by Radu » Tue Jan 19, 2010 11:27 am

Hi Vanchev,

You can regard the Oxygen Author architecture as containing the entire text content of the document as one long string.
Besides the text content there are special marker characters with the value of 0 which indicate the places where the nodes point to in the text content.
There is also a tree-like hierarchy of DOM-like AuthorNodes which point with the getStartOffset and getEndOffset methods to the special marker characters in the content.

This image (which you can also find in the AuthorDocumentFragment Javadoc) should give you a better idea about the architecture:

Image

Here is a sample code which iterates the entire content, finds words of interest (in this case "italic" and "bold"), checks if they are already surrounded with the marker tags, if not, asks the user and surrounds them with the specific tags.

Code: Select all


  /**
* @see ro.sync.ecss.extensions.api.AuthorOperation#doOperation(ro.sync.ecss.extensions.api.AuthorAccess, ro.sync.ecss.extensions.api.ArgumentsMap)
*/
public void doOperation(AuthorAccess authorAccess, ArgumentsMap args)
throws IllegalArgumentException, AuthorOperationException {
AuthorDocumentController controller = authorAccess.getDocumentController();
AuthorDocument doc = authorAccess.getDocumentController().getAuthorDocumentNode();
try {
controller.beginCompoundEdit();
String[] wordsToWrap = new String[] {"bold", "italic"};

//The the whole author content in a segment
Segment seg = new Segment();
seg.setPartialReturn(false);
controller.getChars(doc.getStartOffset(), doc.getEndOffset() - doc.getStartOffset() + 1, seg);

//The whole content of the document (start/end node markers included).
String wholeContentString = new String(seg.array, seg.offset, seg.count);

//Navigate word by word
int currentOffset = 0;
int currentWordStartOffset = 0;
String currentWord = "";
for (int i = 0; i < wholeContentString.length(); i++) {
char ch = wholeContentString.charAt(i);
if(
//Whitespace
Character.isWhitespace(ch)
//Special node markers
|| ch == '\0') {
if(currentWord.length() > 0) {
for (int j = 0; j < wordsToWrap.length; j++) {
if(currentWord.equals(wordsToWrap[j])) {
//Now check if the word is already wrapped in an element
AuthorNode parentOfWord = controller.getNodeAtOffset(currentWordStartOffset);
if("i".equals(parentOfWord.getName()) || "b".equals(parentOfWord.getName())) {
//Node is already wrapped, do nothing.
} else {
//Select the word in the document
authorAccess.getEditorAccess().select(currentWordStartOffset, currentWordStartOffset + currentWord.length());
//Ask the user if he wants to wrap the node
boolean userAccepted = authorAccess.getWorkspaceAccess().showConfirmDialog(
"Title", "Accept wrapping the word?", new String[] {"Yes", "No"}, new int[] {0, 1}) == 0;
if(userAccepted) {
//Wrap the node
String xmlTag = "italic".equals(currentWord) ? "<i/>" : "<b/>";
controller.surroundInFragment(xmlTag, currentWordStartOffset, currentWordStartOffset + currentWord.length() - 1);
//We added a new node which comes with two node markers in the document content so the current
//offset is increased by 2.
currentOffset += 2;
}
}
break;
}
}
//Empty the current word accumulator
currentWord = "";
}
} else {
//Character, accumulate in current word
if(currentWord.length() == 0) {
//Start of new word
currentWordStartOffset = currentOffset;
}
//Add the character to the current word
currentWord += ch;
}
currentOffset ++;
}
} catch(Exception e) {
throw new AuthorOperationException(e.getMessage());
} finally {
controller.endCompoundEdit();
}
}
Regards,
Radu
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

vanchev
Posts: 4
Joined: Mon Dec 14, 2009 8:37 pm

Re: AuthorEditorAccess' select

Post by vanchev » Tue Jan 19, 2010 7:20 pm

Thank you, Radu,
your answer was most helpful.


With Best Regards,
Jivko

Post Reply