Of course, nothing is perfect, and Eclipse has faults just like the rest of us. Living in Java-land, it tends to suffer from what is termed ravioli code, where code is scattered throughout hundreds of tiny, tiny objects. Often, to do what you want to do, you need to define one class which then configured by another class which itself may be generated by some factory object. Often, I find the complex tasks are made very easy, but it can be maddening to track down the documentation for tiny little changes I want to make.
And occasionally, poor design does manage to slip in. Take the argument list tooltip (one of the 3 essential editor components). This handy guy gives you function signatures and a little descriptive documentation. In Cusp, The signature is formatted in bold to make it quicker for your eye to pick out. Displaying the tooltip to the user with the required information was trivial. Making part of it bold, that was the hard part.
Here's a quick overview of the architecture. To get your editor to behave the way you want it to, you subclass TextSourceViewerConfiguration, which then informs the editor how it should colorize syntax, how to indent, how to automplete, etc (most of these configurations involve returning another object that does the actual work). Lest you think this is an unnecessary abstraction, it turned out to be very handy when I wanted to make the input area of the REPL behave like the editor, even though they are different beasts.
In there, we tell the editor about Arglist Assistance as follows:
ca = new ContentAssistant();
ca.setContentAssistProcessor(new ArglistAssistProcessor(editor),
IDocument.DEFAULT_CONTENT_TYPE);
IPreferenceStore ps = LispPlugin.getDefault().getPreferenceStore();
ca.enableAutoActivation(ps.getBoolean(PreferenceConstants.AUTO_POPUP_COMPLETIONS));
ca.enableAutoInsert(ps.getBoolean(PreferenceConstants.AUTO_INSERT_COMPLETIONS));
ca.setAutoActivationDelay(ps.getInt(PreferenceConstants.AUTO_POPUP_COMPLETIONS_DELAY));
ca.setProposalPopupOrientation(ContentAssistant.CONTEXT_INFO_BELOW);
if( ps.getBoolean(PreferenceConstants.ARGLIST_BELOW)){
ca.setContextInformationPopupOrientation(ContentAssistant.CONTEXT_INFO_BELOW);
} else {
ca.setContextInformationPopupOrientation(ContentAssistant.CONTEXT_INFO_ABOVE);
}
...
public IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {
ca.setInformationControlCreator(new LispTextHoverControlCreator());
return ca;
}
As you may or may not have noticed, ArglistAssistProcessor is the class that actually figures out what information to display. It parses the document to find out what function is being called (or if the cursor is even in a place where a tooltip makes sense), then talks to Swank to get the information, and then returns that in a format Eclipse understands. The process may sound a little complex when you first run into it, but it is well-covered in the tutorials, so it's fairly easy to get to this point.
But how do I format that text for easier reading? Here, the documentation failed me. And so I'm writing up the answer as a service to the rest of you who may want to do this.
Part of the interface for IContentAssistProcessor is getContextInformationValidator(), which returns an IContextInformationValidator, the object that determines when it is time get rid of the tooltip. It turns out that to format the tooltip, you need to make this object also implement IContextInformationValidator.
This is bad design for so many reasons. Nothing in the documentation indicates that this is the place to do the formatting, and it makes no logical sense for a validator to also (sometimes) act as a formatter. It is also rather contrary to the usual Java and Eclipse way to take an object designed for a completely separate task, and, if it happens to implement another interface, use it for that as well. I'm pretty sure this was slapped on with little thought.
But now it's documented. If you're wondering how to format your tooltips in your own editor, now you know.
No comments:
Post a Comment