this has been initially posted as part of #72091.
The project UI customizer should be pluggable from 3rd party codebase. Even
though the original submission was just for webapp projects, this is a rather
general issue so probably belongs into the project/projectuiapi module.
pasting from the #72091 issue:
Define some registration mechanism, such as this layer.xml example:
<!-- These panels get placed in the project properties UI -->
Files in this folder denote instances of ProjectAwareUIFactory:
public interface ProjectAwareUIFactory
JComponent createComponent(Project p);
...which are read in CustomizerProviderImpl.init(), and added to the list of
categories and panels.
Hard to suggest something when the request is just vaguely formulated, but I'd
like to stress that the API should be natuarally connected to
ProjectCustomizer and if possible also somehow mimic core/options, so people
who want to add a dialog to project or for tools/options need to do (nearly)
As concern the factory, I would say that it should create directly:
One possible issue is the handling of subcategories, on the declarative layer it
could be solved by folders (one can set displaynames/icons there etc). a
limitation of this is that one cannot have a panel for the node with
subcategories, however I don't think it's an issue as currently all the project
customizers have an empty panel there.
I assume all the panels, even the default ones should be created using this API
and we should have a single factory method in spi.support package somewhere that
would create the customizer for the given layer data. eg.
public static Dialog createCompositeCustomizerDialog(....)
re yarda: creating Category instances is not enough. crutial is the
createComponent(Project p) method that is not part of Category right now.
Additionally the Category instance lists the children panels/categories and
these should be probably also declarative to allow composition of nested categories.
Does the component need to handle OK/Cancel events?
Created attachment 29624 [details]
initial API proposal
Here's the initial API proposal. I've tried to utilize the existing support
classes as much as possible.
1. a factory method in ProjectCustomizer tha creates a dialog based on layer
tree structure content.
2. the layer content is composed of CompositeCategoryProvider instances. The
customizer-to-panel context transfer is done through passing Lookup instance as
parameter. In the lookup one would put the Project instance and/or some custom
API that is to be defined on per project type basis.
3. possible problem area is the creation of Category instances. These can be
currently created using a factory method that includes an array of child
category instances. But with declaratively defined categories it's not
possible/useful to obtain this list from the SPI user's codebase. We could
inject the children at later stage though. The create method allows to pass null
or empty array as children, so we can even use the same factory method.
jglick: just as they currently do. The panels can influence validity of the data
through the Category.isValid()/setValid() method. If one of the panels is not
valid, the customizer should not allow applying the changes.
Created attachment 29752 [details]
complete patch (API+implementation) for projectuiapi
Created attachment 29753 [details]
rewrite of j2seproject type that uses the new api.
I like it. It's an improvement over my initial implementation, which did not
allow subcategories. I have 2 concerns, though:
1. Passing the project's Lookup into the factory methods may not be sufficient.
There's all kinds of info I can get/set on a Project that I cannot get to with
its Lookup. For example, if I'm setting information in the project.properties
file of an ant-based project, I need the AntProjectHelper, which is not in the
Lookup. I'd prefer just passing the Project into the factory methods for this
reason (unless you have a better way of getting to the ant properties using just
2. My implementation adds a single interface, ProjectAwareUIFactory:
JComponent createComponent(Project p);
Though my implementation didn't allow for subcategories, it probably could, with
a little more code on the sysFs introspection code, allow folders. I think this
is easier than having to learn about Categories and Subcategories.
BTW, thanks for taking this up! My work life just got a lot more complicated,
so I'm not moving on this as quickly as I should...
Milosi please do:
cvs di -N
and put a new diff since this one does not contain J2SECompositePanelProvider
which I'm also curious about. Or just attach J2SECompositePanelProvider alone as
an attachment. Thanks.
Created attachment 29777 [details]
file missing from the j2se diff
Rich, re 1:
The lookup passes into the factories/providers is not the project's lookup. It's
a custom lookup created by the customizer implemetation. What is passed in
there is up to the project type. For j2se project I put the J2seproject instance
and a j2seprojectProperties instance. This is a private contract between the
project type and the panels that plug into it. Not to be solved in projectuiapi
the reason for having categories created and passed to panels is because it's a
carrier of communication from panel to customizer. For example it allows the
panels to set valid state and error message. and given it's a class from the api
module used by the providers, it's easy to extend in backward compatible manner.
rich 1: from what I see the context provider is not restricted to pass exactly
Project's lookup. The provider is free in consideration what should be passed in
the Lookup. I.e. the provider "dictates" what others are able to do. So is is
not the API proposed by Milos who restrict you but individual implementator,
e.g. J2SEProject. So you rather need to communicate to idividual providers and
ask them to put something in the lookup. API is benevolent enough. At least this
is how I understand it ;)
Umm, sorry. Did not notice Milos's comment sent just before mine.
One question. The attached implementation behaves in the way that if a provider
returns from CompositeCategoryProvider.createCategory() null, the creation of
category is effectively skipped, i.e. the category is not shown in the project's
customizer without any warnings/errors. I like this behaviour since I'm able to
show my category based on the Lookup content.
Possible usecase: I could implement a general
ProjectCustomizer.CompositeCategoryProvider which I would inject into all
Project's customizers and then very easily "hide" my category for unsatisfactory
contexts (e.g. there is not Project instance in the lookup). But not sure if
this just undocumented feature I can depend on or if I would have to go another
way in the above use case.
I hope that this is just fast draft and Javadoc will be ehnanced a little bit so
e.g. the above will be clear.
- constructor should be private
- use of foreign class in NbBundle.getBundle(CustomizerProviderImpl.class)
Just PMD-ized it ;) I'm curious since API Support customizer... Also thinking
about API Wizard but that's another story depending on the success of review...
AB01: I would suggest not to use a top-level layer folder such as "J2SEProject"
for the customizer. What about creating a hierarchy similar to
Loaders/mime/type/Actions, so maybe Projects/project-type/Customizer? Note issue
72441 seems to use Projects/Nodes/projecttype for now, but I think the former
approach would be better, since everything (nodes, categories, etc.) would be
under a single folder. Of course a project type can ultimately use whatever path
it chooses to, but it would be nice if the Javadoc suggested (and the J2SE
project used) a good value.
AB02: apart from mkleint's comment #3 about injecting the subcategories, the API
does not seem to discourage a client from returning a category which already
contains subcategories (i.e., created by passing a non-null value as the
subcategories parameter of Category.create()) from
DelegateCategoryProvider.create() throws an AssertionError for the subcategories
because they are not in the category2provider map. Perhaps this should be also
I agree with Martin's comment about supporting null values from
Created attachment 29895 [details]
updated diff of projects/projectuiapi
Created attachment 29897 [details]
updated j2seproject changes
mkrauskopf: yes, returning null in CompositeCategoryprovider shall be allowed.
I've updated the javadocs.
AB01: good catch, I've moved the j2se project's customizers to
AB02: I've added an assertion that makes sure noone is returning a category with
Thanks to all for the comments.
about to apply the changes to trunk later this week.
Sorry for the late comments. But it looks good.
For folder name, prefer to use the ant/project project type code as a
convention, so e.g.
instanceClass attr in j2seproject layer is definitely superfluous, and
instanceOf can probably be omitted as well - just instanceCreate is enough here.
jglick: all comments accepted and integrated.
The changes are now in trunk.