Page 1 of 1

Trying to understand Anchors (XTextRange)

PostPosted: Thu Apr 07, 2016 3:54 am
by _savage
I'm trying to understand anchors.

If I look at my document then I can get an iterator over paragraphs and tables (through XTextContent), or an iterator over the graphic elements (through XShape). Both iterators are independent of each other. In both cases though, the elements I iterate over have an "Anchor" property, an XTextRange, and an "AnchorType" (link). It seems that the anchor type indicates how to interpret the anchor itself; for example a AT_PARAGRAPH means that "The anchor of the object is set at the top left position of the paragraph." But which one?

How do these anchors relate to each other, if they do at all? Is there a relative order of text ranges to each other, other than placement on a page?

Re: Trying to understand Anchors (XTextRange)

PostPosted: Thu Apr 07, 2016 9:26 am
by B Marcelly
Property Anchor points to the paragraph where the graphic is anchored.
From the paragraph, getText() returns the text the paragraph belongs to.
In the general case, this text may be the ordinary text you write, or the text inside a text frame, or the text inside a cell of a table, or the text of the left part of the header of the page, or in a Endnote, etc...
Furthermore you can for example have a frame inserted in the main text, and a table inside this frame.
Finding out where is the anchor is nearly impossible in the general case.

Re: Trying to understand Anchors (XTextRange)

PostPosted: Thu Apr 07, 2016 1:06 pm
by musikai
B.Marcelly gives invaluable information.
Perhaps you might find some further infos in this thread:
https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=80329&hilit=anchors

It uses equalunoobjects() to find out where an anchor is anchored in.

Re: Trying to understand Anchors (XTextRange)

PostPosted: Thu Apr 07, 2016 4:55 pm
by _savage
musikai wrote:B.Marcelly gives invaluable information. Perhaps you might find some further infos in this thread:
https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=80329&hilit=anchors

Thank you! The linked thread looks very much like what I'm after, I'll take a good look...

musikai wrote:It uses equalunoobjects() to find out where an anchor is anchored in.

I'm using Python. Any idea how to import this function, or in which module I can find it? There is some talk about equality of Uno structures in Python in the Python Bridge documentation, but not sure that's the right way to go.

Re: Trying to understand Anchors (XTextRange)

PostPosted: Thu Apr 07, 2016 7:22 pm
by karolus
Hallo

_savage wrote:
musikai wrote:B.Marcelly gives invaluable information. Perhaps you might find some further infos in this thread:
https://forum.openoffice.org/en/forum/viewtopic.php?f=20&t=80329&hilit=anchors

Thank you! The linked thread looks very much like what I'm after, I'll take a good look...

musikai wrote:It uses equalunoobjects() to find out where an anchor is anchored in.

I'm using Python. Any idea how to import this function, or in which module I can find it? There is some talk about equality of Uno structures in Python in the Python Bridge documentation, but not sure that's the right way to go.


in Python use `is`-keyword to test Object_Identity:

Code: Select all   Expand viewCollapse view
if some_object is some_may_be_other_object


Karolus

Re: Trying to understand Anchors (XTextRange)

PostPosted: Fri Apr 08, 2016 6:37 pm
by _savage
I still can't quite get this right. For example, in the following code I iterate over all "shapes" (i.e. objects that implement the XShape interface) and I collect the following information: their anchor (i.e. object that implements the XTextRange interface), page number they're currently located on, and their bitmap (BMP, or DIB, device-independent bitmap) if there is one. Finding the page number for a text range as discussed in this thread.

Code: Select all   Expand viewCollapse view
shape_list = [] # New empty list
shape_enum = document.DrawPage.createEnumeration()                           
while shape_enum.hasMoreElements():                                         
    shape = shape_enum.nextElement()                                         
    anchor = shape.Anchor                                                 
    pageno = get_page_no(anchor)                                         
    if hasattr(shape, "Graphic"):
        graphic = getattr(shape, "Graphic")
        bmp = graphic.DIB.value
    else:
        bmp = None
    shape_list.append( (anchor, pageno, bmp) )

Next I iterate over all paragraphs of a document, and I want to check which paragraph has a shape anchored on it. I can always compare the page numbers, but if possible I'd like to be more precise.

Code: Select all   Expand viewCollapse view
par_enum = document.Text.createEnumeration()                                 
while par_enum.hasMoreElements():                                           
    par = parenum.nextElement()                                             
    pageno = get_page_no(par)
    # Iterate over all known shapes and find if one anchors to this paragraph.
    for shape_anchor, shape_pgno, shape_bmp in shape_list:
        if shape_anchor is par:
            print("Found a shape that anchors to this par!")
        if shape_pgno == pageno:
            print("Found a shape that anchors to the same page as this par!")

I am uncertain as to what I'm supposed to compare: that paragraph against the shape's anchor, or the parargaph's anchor against the shape's anchor? And how? Using the "is" keyword as suggested above doesn't seem to yield a match, and I can't find equalunoobjects() in Python's UNO bridge.

Another Python specific problem seems to be the AnchorType enum. How do I import it, and from where?

Code: Select all   Expand viewCollapse view
from com.sun.star.beans import PropertyValue # Works
from com.sun.star.text import TextContentAnchorType # Fails

Above doesn't work, but it does work for e.g. importing the PropertyValue structure.

Re: Trying to understand Anchors (XTextRange)

PostPosted: Sat Apr 09, 2016 4:21 pm
by _savage
For testing purposes I placed the following image into a document, and anchored it to the paragraph.

anchor.jpg

The AnchorType of the graphic object is AT_PARAGRAPH.

When I inspected the Anchor element itself I would have expected its getString() to return the paragraph's text "At the end...". However, it was empty, and the Anchor element doesn't support the com.sun.star.text.Paragraph service, which lets me to think that it's not actually a paragraph!

B Marcelly wrote:Property Anchor points to the paragraph where the graphic is anchored. From the paragraph, getText() returns the text the paragraph belongs to.

Do I compare the graphic's anchor with the paragraph itself, or with the paragraph's anchor? Neither seems to return a match.

Code: Select all   Expand viewCollapse view
if par.Anchor is shape.Anchor # False
if par is shape.Anchor # False

What am I missing?

Re: Trying to understand Anchors (XTextRange)

PostPosted: Mon Apr 11, 2016 12:17 pm
by musikai
I think you would compare Par.text with shape.Anchor. But this will only tell you if the shape is anchored in the same text as the paragraph is in. eg. both are in the same textframe. But you want a more precise information. So your idea of comparing pagenumbers is perhaps the way to go.
Little question: Do you get pagenumber infos when iterating over paragraphs? I thought pagenumber is only available to a viewcursor.

So perhaps you can get and compare some position y infos from the anchor with a paragraph if it has some.
Or: If you select the paragraph text range (via a textcursor) then you should be able to compare if the anchor is in the selected textrange with compareRegionStarts. This is what I did in my link above (but with a manual selection of the viewcursor)

Re: Trying to understand Anchors (XTextRange)

PostPosted: Mon Apr 11, 2016 4:44 pm
by _savage
musikai wrote:Little question: Do you get pagenumber infos when iterating over paragraphs? I thought pagenumber is only available to a viewcursor.

I am using this helper function:

Code: Select all   Expand viewCollapse view
    def get_page_no(textrange):                                                 
        cursor = controller.getViewCursor()                                     
        cursor.gotoRange(textrange, False)                                     
        return cursor.getPage()

and pass shape.Anchor or the paragraph itself. In both cases I get the page number of the element.

Thank you for your other tips, I'll see if I can find more precise information using the coordinates as you suggest. I guess that my interpretation of the meaning of the AT_PARAGRAPH anchor was wrong then?

Re: Trying to understand Anchors (XTextRange)

PostPosted: Wed Apr 13, 2016 1:30 pm
by _savage
musikai wrote:So perhaps you can get and compare some position y infos from the anchor with a paragraph if it has some.

Interesting tip using the coordinates of the anchor's text view cursor. Turns out that that cursor's position is based off of the document's first page, so that paragraphs and graphics have fairly accurate and increasing Y coordinates. Assuming these positions are valid in all cases, that's a close-enough solution to tie a graphic to a paragraph.

Unfortunately, though, the coordinates of a graphics' anchor can be even on a different page than the graphics itself... :crazy:

Re: Trying to understand Anchors (XTextRange)

PostPosted: Wed Apr 13, 2016 6:07 pm
by musikai
Haha, sounds like oo is full of surprises. Btw what do you want your macro to do?

Re: Trying to understand Anchors (XTextRange)

PostPosted: Wed Apr 13, 2016 8:02 pm
by _savage
musikai wrote:Haha, sounds like oo is full of surprises. Btw what do you want your macro to do?

I'd like to "linearize" the text content of a document and its images. I mean, iterate over all paragraphs and read them out, and if there is a graphic object next to the paragraph (whatever "next" means for AOO) then I'd like to extract that as well and tie/associate it with the closest text paragraph.

Re: Trying to understand Anchors (XTextRange)

PostPosted: Wed Apr 13, 2016 8:14 pm
by musikai
Would that be different than switching to web-view?