Jython - как я могу объединить два LeafElements в DefaultStyledDocument?

Я пытаюсь "нормализовать" подкласс DefaultStyledDocument, в том смысле, что мы имеем org.w3c.dom.Node.normalize(): то есть, объединить прилегающий текст "листья". В случае DefaultStyledDocument эти листья идентифицируются для объединения, если два смежных имеют одинаковые атрибуты (или их нет).

Ниже приведена простая версия (мы не проверяем фактические атрибуты: это вариант использования, когда у вас либо простой текст, либо текст с одним возможным стилем разметки).

def normalise( self ):
    # recursive function:
    def normalise_structure( el, depth = 0 ):
        indent = '  ' * depth
        start = el.startOffset
        print( '%s# el %s |%s|' % ( indent, el, self.getText( start, el.endOffset - start )))
        prev_attr_set = None
        for i in range( el.elementCount ):
            subelement = el.getElement( i )
            normalise_structure( subelement, depth + 1 )
            if subelement.leaf:
                curr_attr_set = subelement.attributes
                print( '%s  # this is a leaf, attribs %s' % ( indent, curr_attr_set, ))
                # this is a simple version: only works if there is only one possible attribute
                if prev_attr_set and curr_attr_set and prev_attr_set.attributeCount == curr_attr_set.attributeCount:
                    print( '%s  # %s leaf needs to be merged with previous leaf' % ( 
                                indent, 'marked-up' if prev_attr_set.attributeCount == 1 else 'plain'))
                    attr_set = prev_attr_set.getElement( 0 ) if prev_attr_set.attributeCount else None
                    prev_subelement = el.getElement( i - 1 )
                    prev_start = prev_subelement.startOffset
                    curr_end = subelement.endOffset
                    merged_element = javax.swing.text.AbstractDocument.LeafElement( 
                        javax.swing.text.DefaultStyledDocument(), el, attr_set, prev_start, curr_end  )
                    el.replace( prev_start, curr_end - prev_start, [ merged_element ] )
                prev_attr_set = curr_attr_set
            else:
                print( '%s  # NOT a leaf...' % ( indent, ))
                prev_attr_set = None
    for self_el in self.rootElements:
        normalise_structure( self_el )

Когда я запускаю это, я получаю эту ошибку:

Исключение в потоке "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException в java.lang.System.arraycopy(собственный метод) в javax.swing.text.AbstractDocument$BranchElement.replace(AbstractDocument.java:2290)

Спешу добавить это, прежде чем пытаться javax.swing.text.DefaultStyledDocument() как параметр 1 в конструкторе LeafElement я пытался "self"(то есть DefaultStyledDocument, который вызывает normalise на первой строке): та же ошибка.

1 ответ

Решение

Да, можно сделать:

AbstractDocument.BranchElement.replace() выглядит так:

public void replace(int offset, int length, Element[] elems)
  ...

Оказывается, что здесь "смещение" и "длина" относятся к подэлементам BranchElement (обычно LeafElements), а не к смещению и длине основного текста в StyledDocument.

Кто-нибудь умнее меня получил бы это раньше. Документация по API (Java 7) может сделать это немного понятнее....

Другие вопросы по тегам