Adding shortcuts to scrollbar via workspace access plugin

Having trouble installing <oXygen/>? Got a bug to report? Post it all here.
Radu
Posts: 5088

Re: Adding shortcuts to scrollbar via workspace access plugin

Wed Aug 16, 2017 8:32 am

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
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com
Radu
Posts: 5088

Re: Adding shortcuts to scrollbar via workspace access plugin

Wed Aug 16, 2017 4:01 pm

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-oxygen-sdk-part-2-frameworks.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/18/ug-editor/tasks/dg-extensions-bundle.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
Radu Coravu
<oXygen/> XML Editor
http://www.oxygenxml.com

Return to “Common Problems”

Who is online

Users browsing this forum: No registered users and 2 guests