The goal of this task is to separate the API and
SPI in looks. There currently is some kind of
separation, but it still requires clients to deal
with Look class - call into it, and we want module
to subclass Look as well. We have long history of
problems like this and it would be better to
separate the API from SPI.
Another (side) goal is to make looks a bit
generic. To act as lookup provider for any kind of
Created branch for openidex/looks named aspect_33268 rooted at
Initial part of the rewrite is availabe under the tag
it contains rewrite of the LookNode that is not calling directly to
Look, but is using a wrapper called LookLookup (implementation of
Lookup) to query various values. For a communication between the node
and the lookup a set of interfaces Aspect.Hierarchy, Aspect.Image,
Aspect.Identity, Aspect.Description has been introduced. The
LookLookup implements them and delegates to methods in Look.
So we have reached the separation of API and SPI. Look is pure SPI and
the API is a set of interfaces that can be obtained from the thru a
Lookup available for any Object.
Hrebejk, I have a better implementation of Lookup based on
getLookupItems than is in your branch. Consider merging
LookLookup.java ideas rev.
Merging differences between 184.108.40.206 and 220.127.116.11 into LookLookup.java
Listening on changes implement and tagged as
now the LookNode listen to changes generated by the LookLookup and
correctly refires the changes to the best possible extent. That means
not all test passes, but they which do not - cannot - they are
restricted by the new design that joins together for example icon
change and openedIcon change. Then it is impossible to distinguish
such events, but that does not seem to be big problem as the reaction
to those events is the same in both cases anyway...
The pre-final stage has been hit. Marked by a tag
it comes with greater API changes. LookDescritor has been renamed to
Aspect and it provides the basics for defining Lookup for an Object.
So it contains the getLookupItems () method. In future one could
provide just Aspect to provide information about the object. Look is
just convinient SPI that simplifies writing of common aspects like
Aspect.Description - instead of writing an interface, we can just
overwrite a method.
Event API simplification phase finished. Tagged as
it brings major improvements to the complexity of API (LookListener
and LookEvent deleted) while preserving the functionality and SPI
(methods Look.fire* still implemented in the same way). The only thing
missing now is a pluggable API<->SPI mapper, but that is an open
solution for future.
The last step (before merge - if the merge is ever going to happen) is
to move all Look* classes from API to SPI packages. Now they are pure SPI.
I do not think addAspectListener, removeAspectListener, and
fireLookupItemsChange should be final in Aspect. That prevents anyone
from ever implementing them more efficiently. Better, they should be
abstract in Aspect (i.e. make it essentially an interface), and
defined as final only in Look (or in some intermediate SPI class, e.g.
I don't understand the purpose of Aspect.getLookup - it will not work
unless the arg is instanceof Look. Probably it should use one impl if
instanceof Look and another impl otherwise. Also LookLookup should
probably be using Proxy to handle interfaces not represented in
Aspect.*, right? Or is this already handled some other way?
I don't think all these Aspect.* interfaces should be nested classes.
They are public and quite visible in the API. Better IMHO to make them
top-level, e.g. DataTransferAspect.
"I don't understand the purpose of Aspect.getLookup - it will not work
unless the arg is instanceof Look." - I now see that non-Look
subclasses of Aspect cannot be constructed at all! This is a temporary
hack I hope?
Right now the Look is the only allowed subclass, I'll work on it in
Maybe AspectProvider should be an interface; don't see any particular
reason for it to be a class.
I see that aspects are now named e.g. "Help". Might be better to name
them e.g. "HelpAspect" - much clearer what is going on when you are
importing a lot of packages. Compare e.g. "OpenCookie".
There are some problems with excluding org.netbeans.api.aspects from
the public packages.
1. Look now extends an inaccessible class. This may cause linkage
errors for SPI users. Also, addAspectListener takes an inaccessible
parameter, so you cannot use it to listen to looks from outside the
2. fireLookupItemsChange now requires a Class parameter that you
cannot create as an SPI extender. Could be worked around by making
that private and re-adding e.g. fireDisplayNameChanged, etc.
BTW the event method name should probably be "lookupItemsChanged" not
"lookupItemsChange" for consistency with ChangeListener and
LookupListener and many other listener interfaces (tho not
In openide/looks the looks are an SPI. The aspect API is not used.
Let's leave this issue to track the work on the branch.
Most of the work is in modules under contrib/aspects:
No time to work on that right now.