I want to add a "hyperlink" element to a Document -- a stretch of text (or possibly an image) that responds to a user click by doing something (typically visiting a web page). At first blush, I thought, I'll subclass TextNode and add a mouse listener to it. That's wrong on a bunch of fronts -- TextNode is final, TextNode doesn't have appearance properties, and Document elements do not support mouse listeners.
So after much consideration, I did the following, which mostly works (but see question 2): I subclassed Span to produce a new Element called Hyperlink. It sets its style properties suitably for a link (for now, that just means setting color blue). In its simplest form, it has a constructor that accepts a string of text and a url, and adds a TextNode to itself containing the text. I then subclassed TextPane and its Terra skin. In the skin, I override mouseDown/Move/Up. In each of those, I locate the element under the mouse and if it is of type Hyperlink take appropriate action. To determine the element under the mouse, I call Document#getInsertionPoint to get an offset, then Document#getNodeAt to get a Node. If the Node is a Paragraph p, I further call p.getDescendantAt(offset - p.getOffset()) to get a simpler Node. Then I fetch the parent of the node and test whether it is an instance of Hyperlink. (1) This approach mostly works, but seems kludgy. E.g., it implicitly requires that Hyperlink only appear inside my new TextPane subclass. Is there a better approach? (2) When the mouse hovers over a Hyperlink, I'd like to underline the link text. However, calling setUnderline does not have an immediate effect -- the underline doesn't appear until I either click or take focus out of the application (e.g., by Windows' Alt-Tab). Is this a bug, or is there some method I need to call? I traced thru the code, and it looks like there is a listener on the span that calls underlinedChanged and ultimately repaint, but the Eclipse debugger gets confused about where it is, so I can't tell for sure that repaint really gets called. (3) Once in a while, Document#getInsertionPoint returns -1 for no apparent reason. Unfortunately, I don't have a test case at this point.
