Page 1 of 1

API for customizing olinik insertion

Posted: Sun Sep 05, 2010 6:28 am
by dcramer
Hi there,
At some point, I would like to customize oXygen's olink dialog so that if you are inserting an olink where the targetptr ends in a certain string (i.e. ".glossary"), clicking OK inserts a glossterm with the value of the targetptr stored in some attribute.

This would allow us to use the olink insertion dialog as a way to insert glossary terms from a master glossary in addition to regular olinks.

Would this be possible using existing APIs or should I look for other ways to do this?

Thanks,
David

Re: API for customizing olinik insertion

Posted: Mon Sep 06, 2010 10:44 am
by Radu
Hi David,

All custom Author operations are written using the Author Java API.
What you need to do in order to make such customizations is to start looking over the Author SDK kit and the included PDF file:
http://www.oxygenxml.com/developer.html ... horing_SDK

The main idea is that in the Oxygen Installation directory in the "framworks/docbook" directory there are two *.framwork XML configuration files (which get saved when you edit the frameworks from the Oxygen Preferences->Document Types Association option page) and a docbook.jar which contains compiled Java code for the operations defined for both the Docbook 4 and Docbook 5 frameworks.

The Author SDK comes along with sources for the Docbook customizations so what you could do would be to modify and recompile those sources back to the jar file.

Then you would share the whole "docbook" framework directory with the other users.

Regards,
Radu

Re: API for customizing olinik insertion

Posted: Mon Jan 31, 2011 4:02 am
by dcramer
Ok, I've taken a look at ro.sync.ecss.extensions.docbook.olink.InsertOLinkOperation and it seems that there's not much going on in that class. Most of the logic must be in ro.sync.ecss.docbook.DocbookAccess, but that's in oxygen.jar.

The modification I need to make for our situation is that if the targetdoc is a certain value ("Glossary"), then instead of inserting an <olink> the tool should insert something like <glossterm linkend="whatever.glossary">Whatever</glossterm> (where the text of the glossentry/glossterm is Whatever and the xml:id is whatever.glossary). To do that, I think I need to reimplement DocbookAccess.insertOLink, but I still need insertOLink to do most of the stuff it does now (but handle the special case when the targetdoc is "Glossary". I'm learning Java as I go on this, but I think I need the source for DocbookAccess to do this (i.e. I can't just extend it).

Thanks,
David

Re: API for customizing olinik insertion

Posted: Mon Jan 31, 2011 11:29 am
by Radu
Hi,

Most of the code in the extension implementations for Docbook, DITA, etc is exposed but sometimes some operations need some more complex GUI functionality like the quick search in the Insert OLink dialog.

You have two possiblities:
1) Call the DocbookAccess.chooseOLink(AuthorAccess authorAccess) static method which shows the dialog and returns the chosen values in an information object. Then process the information and insert your own XML fragment (make sure that the inserted XML fragment is explicitly set in the Docbook 5 namespace, see the code below).

2) There is another workaround which you can use to obtain the desired result.
In the doOperation method you can let Oxygen to insert the olink element and then retrieve the information you need from it, remove it and insert your custom XML fragment.
You can find bellow a sample code that does this:

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 {
authorAccess.getDocumentController().beginCompoundEdit();
try {
Object namespaceObj = args.getArgumentValue(NAMESPACE_ARGUMENT);
// Show the OLInk dialog
DocbookAccess.insertOLink(authorAccess, (String) namespaceObj);

try {
int caretOffset = authorAccess.getEditorAccess().getCaretOffset();
AuthorNode possibleOlinkAtCaret = authorAccess.getDocumentController().getNodeAtOffset(caretOffset);
if(possibleOlinkAtCaret.getType() == AuthorNode.NODE_TYPE_ELEMENT) {
AuthorElement olinkAtCaret = (AuthorElement) possibleOlinkAtCaret;
if("olink".equals(olinkAtCaret.getLocalName())) {

//The caret is inside an link.
String targetDoc = olinkAtCaret.getAttribute("targetdoc").getValue();
String targetPtr = olinkAtCaret.getAttribute("targetptr").getValue();

//Here you can decide whether to replace or not the element

//And if you want to replace:

//Now remove the olink element completely
boolean deleted = authorAccess.getDocumentController().deleteNode(olinkAtCaret);

if(deleted) {
//And insert your own element
//<glossterm linkend="whatever.glossary">Whatever</glossterm>
authorAccess.getDocumentController().insertXMLFragmentSchemaAware(
"<glossterm xmlns='http://docbook.org/ns/docbook' linkend=\"" + targetDoc + "." + targetPtr + "\"></glossterm>",
authorAccess.getEditorAccess().getCaretOffset());
}
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
} finally {
authorAccess.getDocumentController().endCompoundEdit();
}
}
Regards,
Radu

Re: API for customizing olinik insertion

Posted: Mon Jan 31, 2011 10:01 pm
by dcramer
Hi Radu,
I picked method 2 and it works beautifully.

Thanks!
David