Page 1 of 1

Re: Adding shortcuts to scrollbar via workspace access plugin

Posted: Wed Aug 16, 2017 8:32 am
by Radu
Hi Matthew,

Sorry but we do not have such API exposed.
Could you tell me more about your use case? Do you have an XML Schema opened and you want to see where in the schema an element is referenced?

Regards,
Radu

Re: Adding shortcuts to scrollbar via workspace access plugin

Posted: Wed Aug 16, 2017 4:01 pm
by Radu
Hi,

Maybe I can tell you about something similar we implemented.
Let's say you open this sample file OXYGEN_INSTALL_DIR\samples\tei\TEI-P5.xml which is a TEI document (a custom XML vocabulary used to encode old manuscripts) in the Text editing mode. And you find in it this div:

Code: Select all

 <div xml:id="P1">
.....
If you place the caret inside the xml:id value you will get highlighted on the scroll bar all references to it.
So how does it work? This is not a plugin customization but a framework customization:

http://blog.oxygenxml.com/2014/08/the-o ... works.html

In the Oxygen Preferences->Document Type Association page there is a document type association called TEI P5. It's activated when a TEI document is opened and it provides besides a default schema and CSS for visual editing also an extension JAR library in its "Classpath" tab.
In the "Extensions" tab there is a custom extensions bundle implementation set. The TEIP5ExtensionsBundle implementation is defined in that custom JAR library:

https://www.oxygenxml.com/doc/versions/ ... undle.html

and it overrides a method in the base:

Code: Select all

  
/**
* @see ro.sync.ecss.extensions.api.ExtensionsBundle#createIDTypeRecognizer()
*/
@Override
public IDTypeRecognizer createIDTypeRecognizer() {
return new TEIP5IDTypeRecognizer();
}
That TEIP5IDTypeRecognizer is responsible for recognizing IDs and ID references.
It's Java source looks like this:

Code: Select all

/**
* Implementation of ID declarations and references recognizer for TEI P5 framework.
*
* In this framework the IDs are declared in attributes with name 'id'. The references are recognized
* in attributes ptr/@target or ref/@target, see http://www.tei-c.org/release/doc/tei-p5-doc/en/html/ref-ptr.html.
*
* @author radu_pisoi
*/
@API(type=APIType.INTERNAL, src=SourceType.PUBLIC)
public class TEIP5IDTypeRecognizer extends IDTypeRecognizer {

/**
* @see ro.sync.ecss.extensions.api.link.IDTypeRecognizer#detectIDType(java.lang.String, ro.sync.contentcompletion.xml.Context, java.lang.String, java.lang.String, java.lang.String, int)
*/
@Override
public List<IDTypeIdentifier> detectIDType(String systemID, Context context, String attrName,
String attrNs, String attributeValue, int offset) throws CannotRecognizeIDException {
List<IDTypeIdentifier> idTypeIdentifiers = new ArrayList<IDTypeIdentifier>();

if(attributeValue != null && attributeValue.trim().length() > 0) {
if("id".equals(attrName)) {
// xml:id attribute
DefaultIDTypeIdentifier idTypeIdentifier = new DefaultIDTypeIdentifier(attributeValue.trim(), true);
idTypeIdentifiers.add(idTypeIdentifier);
} else if("target".equals(attrName)) {
// 'target' attribute
Stack<ContextElement> elementStack = context.getElementStack();
if(!elementStack.isEmpty()) {
// For ptr/@target or ref/@target the ID references are recognized if the attribute value
// has the pattern #id1 #id2
String idValue = null;

StringTokenizer stringTokenizer = new StringTokenizer(attributeValue, " ", true);
int idx = 0;
while(stringTokenizer.hasMoreTokens()) {
String nextToken = stringTokenizer.nextToken();

if(offset < idx) {
break;
}

if(idx <= offset && offset <= idx + nextToken.length()) {
// Current token include the offset
if(!nextToken.equals(" ")) {
idValue = nextToken;
}
break;
}

idx += nextToken.length();
}


if (idValue != null && !"".equals(idValue.trim()) && idValue.startsWith("#")) {
idValue = idValue.substring(1);
if (idValue.trim().length() > 0) {
idTypeIdentifiers.add(new DefaultIDTypeIdentifier(idValue, false));
}
}
}
}
}

return idTypeIdentifiers.isEmpty() ? null : idTypeIdentifiers;
}

/**
* @see ro.sync.ecss.extensions.api.link.IDTypeRecognizer#locateIDType(java.lang.String, ro.sync.contentcompletion.xml.Context, java.lang.String, java.lang.String, java.lang.String, ro.sync.ecss.extensions.api.link.IDTypeIdentifier, short)
*/
@Override
public int[] locateIDType(String systemID, Context context, String attrName, String attrNs,
String attributeValue, IDTypeIdentifier idIdentifier, short mode) {

int[] idLocation = null;

if ((mode & MODE_LOCATE_DECLARATIONS) != 0) {
// xml:id declaration
if("id".equals(attrName)) {
idLocation = new int[] {0, attributeValue.length()};
}
}

if ((mode & MODE_LOCATE_REFERENCES) != 0) {
if("target".equals(attrName)) {
Stack<ContextElement> elementStack = context.getElementStack();
if(!elementStack.isEmpty()) {
String idValue = idIdentifier.getValue();
String textToFind = "#" + idValue;
int indexOf = attributeValue.indexOf(textToFind);
while (indexOf >= 0) {

if(indexOf + textToFind.length() == attributeValue.length() ||
attributeValue.charAt(indexOf + textToFind.length()) == ' ') {
idLocation = new int[] { indexOf + 1, indexOf + 1 + idIdentifier.getValue().length() };
}

if (idLocation != null) {
break;
} else {
indexOf = attributeValue.indexOf(textToFind, indexOf + textToFind.length());
}
}
}
}
}
return idLocation;
}

/**
* @see ro.sync.ecss.extensions.api.link.IDTypeRecognizer#isDefaultIDTypeRecognitionAvailable()
*/
@Override
public boolean isDefaultIDTypeRecognitionAvailable() {
return false;
}

/**
* @see ro.sync.ecss.extensions.api.link.IDTypeRecognizer#isIDTypeRecognitionAvailable()
*/
@Override
public boolean isIDTypeRecognitionAvailable() {
return true;
}
}
So if your case resembles this case you may be able to implement it at framework level using this extension.

Regards,
Radu