Tasklist API proposal rough draft -- please provide feedback
Tor Norbye <[email protected]>
| Newsgroups | gmane.comp.java.netbeans.modules.tasklist.devel |
|---|---|
| Message-ID | <1035432447.12064.154.camel__665.887088007544$1054569787@proto> |
You may have seen some discussion of the "assistants" proposal
(http://ui.netbeans.org/docs/ui/assistants/assistants_proposal.html)
on the alises; part of it deals with the tasklist. We will have a new
"Suggestions" window where various tools can post suggestions that may
be relevant to the user; The import tool may suggest cleanup when it
discovers files needing work. The CVS module may point out a merge
conflict needing to get resolved. etc.
Here's a link to a proposal dealing with the tasklist specific aspects
of the assistants proposal:
http://tasklist.netbeans.org/proposals/suggestions.html
My goal is to write an API for the tasklist such that other NetBeans
modules can start providing suggestions to the tasklist.
Before putting together a specific API proposal in the form of
javadocs, I'd like to describe it here, to get general agreement.
These are the participants in the API:
- "Suggestion". This represents the actual items shown in the
suggestions list. This is simply a final class with some attributes,
such as a description, an icon. (And probably a priority, a
category, and an optional associated file position or url.)
- "SuggestionType". Each suggestion has an associated suggestion type;
there may be many suggestions for a particular type. Users can
disable suggestions by type. They can also filter the suggestions
window by type, to for example only show audit-suggestions.
- "SuggestionManager". Manages the list of suggestions. To add a new
suggestion, you register it with the suggestion manager. The
suggestion manager also knows if a SuggestionType is disabled or
not.
- "SuggestionProvider". A client written to specifically produce
suggestions (more about this later). This is a SPI; you don't have
to be a SuggestionProvider to register suggestions. But
SuggestionProviders are automatically "awakened" if they are enabled
and the suggestions window is made visible, for example.
- "ActionPerformer". Each suggestion has an associated action.
For the Import tool, it may be modifying your document to
clean up the import statements. For the java-compiler-error
suggestion, it may be moving your cursor and focus to a particular
source code line. You register an ActionPerformer on the suggestion
when you create it.
There are two types of suggestion window clients:
- Clients which are already doing some work, and as a side effect
would like to also create a task.
For example, the Java background parsing task discovers errors.
These (their compiler error message and source position) could be
added as tasks as well - so instead of just seeing error glyphs in
the editor the user can also see the error messages and can double
click on them to warp to the right source line.
Code might look something like this:
String suggestionType = "beepid";
SuggestionManager mgr =
(SuggestionManager)l.lookup(SuggestionManager.class);
if ((mgr != null) && mgr.isEnabled(suggestionType)) {
Suggestion s = new Suggestion(suggestionType);
s.setSummary("Ring the system bell to annoy neighbors");
s.setDetails("Ring the system bell 3 times, then quit. Will echo
\007.");
s.setPerformer(new ActionListener() {
public void actionPerformed(ActionEvent evt) {
beep(); beep(); beep();
}
});
mgr.addSuggestion(s);
}
This should be pretty obvious; we find the manager (if it's null the
tasklist module is probably not enabled), ask it if the kind of
suggestion we're about to make is welcome by the user, and if so
create it and register it. We associate an action to be performed with
it, and also a details panel which the user will be presented with
before the action is performed. (If null, there is no confirmation
step, and even when non-null, the user will be able to say "don't ask
me in the future", and the SuggestionManager will remember that and
skip the confirmation step for this type of suggestion).
The idea here is that some users don't want for example the import
tool to keep checking their source code and make suggestions, if they
don't like its solutions or if they prefer to do it by hand. Having it
there adds clutter and takes up some cycles.
- Clients which are written specifically to provide suggestions.
For example, the Import tool could now get a suggestion provider
which listens for document activation, and when it sees one, checks
to see if it has suggestions to make, and if so, provides them.
It's conceivable that the Audit module could be written in this way
for example; instead of an explicit "Audit..." action, it's always
auditing source files in the background.
This works on a timer, so if you sit idle in the editor for a while,
the suggestion checkers will kick in. The SuggestionManager will
probably time the suggestion providers, and do something "smart"; for
example, a really slow suggestion checker will be run frequently, and
if after say consulting the first 3 suggestion providers we've used up
N milliseconds, it may stop working for another couple of seconds, and
then resume notifying suggestion providers.
SuggestionProviders of this type will simply subclass one of the
SuggestionProvider SPI classes. I can imagine at least two such
classes. DocumentSuggestionProvider which has methods like
"documentOpened", "documentClosed", "documentShown",
"documentHidden", "documentEdited". These get called (after a
timeout - well, documentHidden and documentClosed are called
immediately) when something happens in the editor. So all the Import
Tool has to do for example is subclass DocumentSuggestionProvider,
react to the methods to initiate and abort import statement
scanning.
Best of all, the DocumentSuggestionProvider is registered in the
module's layer file. The class is only instantiated if the Suggestions
Window is opened - and of course if a suggestion type is disabled the
object doesn't get created. So the point is that there is no
performance overhead for adding these providers, other than when the
Suggestions window is actually made visible - and in that case it's
likely that the user wants these suggestions.
Other provider classes include NodeSuggestionProvider, which is called
when the active node changes. For example, a specific
HelpSuggestionProvider extends NodeSuggestionProvider may check the
node to see if it has an associated help context, and if so add a
suggestion to show a particular help topic (and it will also remove
its previously added help topic in any case such that only help topics
for the current node are shown).
Note that I've glossed over SuggestionTypes. I don't want to force
clients to actually create classes for this. A suggestion type, as
far as client code is concerned, really just has an id (so it can be
referred to), and a description (so it can be shown in filters,
options, etc.) and this can be registered in a layer file. The id is
the layer file name.
I haven't quite decided what to do with the "ActionPerformer". I
could use standard interfaces like Runnable or ActionListener, or
invent something new.
For now I'm thinking suggestions expire when you exit the IDE; if we
want to make them longer-lived we have to come up with something more
clever for the action performers (some kind of encoded URL's?).
My intent is for the above classes to be rolled into a
tasklist-api.jar autoload module, which modules can depend on.
So.... that's the rough overview of what I'd been planning. Does this
sound acceptable? If so, I'll add specific javadoc skeletons so you
can start nitpicking classnames, classes vs interfaces
^H^H^H^H^H^H^H^H^H no no not that flamewar again...)
Warning - while criticism is welcome I want productive criticism, in
other words counter proposals or specific suggestions for how to
change it.
-- Tor