In our plugin we add an extension to the message packet. When the message is received, we render the extension to the TranscriptWindow/ChatArea as a link, e.g. "xxx://spiffyLink". Then when the user clicks the link, we have a LinkInterceptor detect that the link is one of ours and do amazing things (open a Window and draw stuff).
But... We''d like to add a contextual menu to the link (see handlePopup() in ChatArea.java). One way to do this would be to add some ContextMenuListeners to the the existing handlePopup(). Unfortunately, the current popup handling occurs the same ANYWHERE in the TranscriptWindow. There is no way for a ContextMenuListener to detect what, if any, element/object was clicked on (see checkForLink in ChatArea.java).
Hmm... So maybe we can just change the LinkInterceptor around to always bring up a contextual menu. Oops. All the LinkInterceptor gets is the String of the link. There is no way to know WHERE the click occured, and so no way to draw the popup in the right place.
What I believe is needed is for the ContextualMenuListener and/or the LinkInterceptor to be passed the MouseEvent so that they can have more visibility to what caused them to be fired. I believe from there, both things could figure out where in the TranscriptWindow the click occured, and get the link info.
Another way I think this could partially be handled is by creating a custom insertLink() that uses a new attribute, e.g. "xxx" and then add a MouseListener that checks for the "xxx" attribute just as ChatArea.mouseClicked() does. Then, normal clicks could bring up a contextual menu. Unfortunately, this does not solve the contextual menu problem (where normal click performs a default action and e.isPopupTrigger() draws a popup). Spark''s popup will be drawn on e.isPopupTrigger(). So, this is half a solution.
Another solution would be to insert a Component into the ChatArea''s Document and add a bunch of custom mouse event handlers to it. But that seems rather harsh when the LinkInterceptor and ContextualMenuListener are so close.