Yet Another Reusable Display Architecture
$Revision: 1.29 $
Changes: available in
CVS
Status: draft
Problem
At least since release 3.2 of the NetBeans IDE, but very likely long time ago
people writing NetBeans modules were struggling with presentation of various
data structures and by finding ways to make this work in modular NetBeans
architecture.
Local solutions were always found when they were really needed, but they differ
in their appearance, APIs and capabilities. They are written by different
groups and as such they just increase the amount of code we have to maintain,
fix and we are not able to reuse it.
A general and reusable display framework would simplify the maintanance and
provided a guidance to all module writers and NetBeans API users. It would
allow them to reach the best quality code with less effort and prevent needless
reinvetion of a new wheel.
History
This is not the first effort to design such general reusable display framework
like this. After release of NetBeans 3.2
Petr Hrebejk started
an ambicious project
with the goal to improve our existing
Nodes API and provide solution
to problems that were hard to solve then named
Looks (see
his original document).
The vision of Looks is described in an overview
describing problems that have to be solved and solution we can get. The
design is covered in a separate document and there
is list of known problems in his solution.
Later more projects based on this idea crystalized. The looks matured
(see issue 18177),
they were simplified
(see enode)
or completely
carbonized, formed a base for a paper about
clasification frameworks,
but none of these projects ever made it into NetBeans release.
The only one that made it into regular build is
viewmodel
which managed to sneak in as a support library for new debugger APIs.
All of these projects solve similar set of problems each using a bit
different style each having its weaker and stronger aspects and admirers.
A search for a common replacement, that is going to happen on this page,
thus shall start with with thoughtful formulation of goals and needs:
Goal
Provide a general, extensible and resuable infrastructure that will be
capable of replacing the current local solutions and will provide easy
adoption and migration path to be in wide use
in near promotion.
What Our Developers Say
I need to enhance a visualization provided by other module
-
add and remove actions into popup menu, reorder existing ones,
change icon, annotate display name, add additional or remove some
children and
best of all this shall be done without the dependencies between
those modules
- Extensions and implementations of debugger modules (JPDA, JSP debuggers, J2EE)
need to customize hierarchy of nodes in various debugger views.
- JSP
debugger takes all nodes from the Locals view and packages them into
several groups (Implicit variables, etc.) thus changing hierarchy of
nodes completely
- EJB
module takes nodes from Call stack view and hides stack frames from
application server to clear the view to show only important
information
- JPDA
debugger alters names of Hashtable entries to (key=>value)
I need to allow other modules to enhance my view
- moreover I may need
more than one presentation of my data (either in list or in a tree,
with or without the root being visible)
-
XML module is extensible by external
modules in a way that they can provide actions that act on XML nodes.
Furthermore, providers of
XML actions provide actions based on the XML doctype which is
supplied to them by the XML module when they are asked for actions.
-
A module has to have the control of what extensions will be applied to their nodes.
For example, the UML Element node might choose to include in its popup
menu actions from VCS module but exclude actions from Code Beautifier
module.
I need colorful visualization of element
- different fonts,
different colors, styles, stroked text, etc.
I need a special capability to be negotiated
- like in case
of html display name or pluggable functionality for shortening
descriptions.
I need to react to changes in list of modules
-
when a new module providing additions to my view is installed or
one of them is disabled I need my view to be updated accordingly.
When more elements is selected
the actions invoked need to
act on all of them even if they are provided by different modules,
in the best case atomically on all of them at once.
New ways to look at java sources are needed
. Just list of
methods and fields (plus beans view sometimes) is not enough. In
J2EE 1.5 the methods will be annotateable with annotations and
some of them will have special meaning. We need to enhance
java classes in J2EE 1.5 project to show list of bussiness methods,
factory methods, etc. But maybe a special filter for navigator
view would be enough as well.
-
In case of an XML file representing file system, the XML module can display a given
XML file as a normal XML file (children of the node are XML elements)
or it can display it as a file system (children of the node are file
objects). User can choose which view is more appropriate and can
switch between them.
The external module must be able to change properties
of
elements. This applies both to property sheet as well as to tree
table view, where also the order is significant and is subject
to customization as well.
-
Extensions should be allowed to extend
node properties and to add more column to tables and tree tables.
Native debuggers would, for example, add a new property PC (program
counter) to call stack or thread views
Whenever a change in certain capabilities of an object happens
- like
change of a property or name or set of subchildren - the
view has to be effectively updated
to reflect the current state.
For my navigator module I will need to negotiate
following capabilities
:
The default action on
an element or what shall happen during drag and drop.
It is likely
that in future we will need really big tooltips (defacto own
window with scrollbars, hyperlinks, etc.) showing at position specified
by the module. Also various scrollbar policies will need
to be negotiated with providing modules. There will be need for
a way to display the empty state (like no members
or
empty java class
). The component with filters will also
need to change in navigator and follow the selection of active document.
- JPDA debugger extends integer
variables' popup menus with Display As Dec,Hex,Oct,Bin menu.
-
I need to pass thru the context
in which I am asking for
special capability - the project I am in, the DOCTYPE of XML document,
instance of class in which the method is supposed to be called, etc.
I need to allow extensibility of projects UI
- for example
there is a need for a struts project to enhance the standard web
project with new nodes.
There is a need for fast search
- after pressing a key the
window where user can type shows and either the selection changes
according to typed text or only elements that match stay visible.
Do not waste our memory
- Right now, when one wants to
modify behaviour provided by other module, the common technique is
to use FilterNode over node provided by other module. This is not
very programmer and memory friendly and given the fact that this is common task,
it shall be supporter in much simpler way.
I really need some support for writing reponsive views
-
I would very warmly welcome a standardized way to write responsive
UI application. It is pretty clear that as soon as I start to delegate
to 3rd party modules, my component will start to underperform.
I'd like to reuse simple and standard infrastracture that would deal
with such situation and prevent UI freezes.
- Version control systems need to be
able to present versioning status (up to date, modified, removed,
etc.) of files. These statuses are expected to be visible in the
following places:
- nodes in file explorer –
file's label and/or icon is changed according to its status in VCS.
Common practice is to alter color or text of file and folders
labels
- nodes in logical views (trees,
tables) – when a module creates some sort of logical view that
contains visual elements that intuitively map to files (Project
view), its elements should contain versioning annotations
- editor panes – editor pane's
title, tab and other gadgets that display file's name should be
annotated as well
-
It would be nice to have means of
ordering of GUI extensions and/or means of choosing one that will be
used if multiple extensions are found:
- XML module selects the extension
that more closely matches the given doctype
- VCS annotations may come from VCS
or EJB module, whichever 'understands' the given node better
- Versioning status may change asynchronously, thus visual components must
listen for changes in annotations or update themselves by other means.
- Version control systems provide
actions (update, commit, diff, etc.) that act on set of files. These
actions are supposed to be accessible from the following places:
- nodes in file explorer –
every file or folder that is under version control has to include
versioning actions in its popup menu
- nodes in logical views (trees,
tables) – every visual element that intuitively map to a file
or set of files (package node) should contain versioning actions in
its popup menu
- editor panes – editor's
popup menu could contain versioning actions as well
- Versioning systems may provide an extension that would allow the
user to switch from the default view of the node to “history”
view of the node where original node's children would be replaced by
children representing previous versions of the file.
- Debugger
views are by default asynchronous because they often cannot provide
data to GUI in real time. Therefore core debugger must cope with this
internally and cannot require that extensions that plug into it all
solve this issue. Extensions should be allowed to block for an
unspecified amount of time in their methods.
- Need an easy way to add custom actions to existing Node (files) in filesystem
tab. We would like to add "Share file" action to any node in the Project Tab
(#56214).
What We Think Our Developers Are Searching For
The purpose of this section is to group and sort the developer opinions into
fewer, bigger and more structured chunks. We shall agree that they sufficiently
match the individual opionions and are really critical for success of this
yet another reusable display architecture effort
.
Guidelines
From the amount of gathered feedback and also from few individual items
(namelly
#19,
#20,
#26) it seems clear that there is
a real need for a solution to these kind of problems. People are searching for guidelines
how to write extensible UIs, how to correctly establish communication between
their and other modules and how to achieve good enough performance.
Visualization In Standard Views
Obviously the most visible need for extensibility is in our current
explorer views and as such it seems to be the most requested feature
(
#1,
#2,
#4,
#12,
#13,
#16,
#18,
#21,
#24). Developers call for possibility to
extend actions, properties, names, children, icons of nodes
in our current views.
Invite Participants
Certain comments (
#3,
#5,
#22,
#28) suggest that the mutual
cooperation shall not be completely chaotic. Developers tend to want to
have control over the places where the participation is going to happen and
sometimes they even desire to select from multiple participants the most
suitable one(s).
Extensible Contract
No matter how carefully we select the set of supported
visualization
aspects
the list will not be complete as can be seen from some surprising
requests (
#6,
#7,
#15,
#17,
#18). If this
effort is supposed to be useful for these developers as well, it has to provide
easy extensibility for both side of the contract.
Lifecycle
The display architecture needs to present not only static data, but be ready
for changes in them or even invoke certain operations on them (
#8,
#9,
#14,
#23). The views must react to changes in set of modules,
in the objects itself and effectively update itself according to those changes.
They must be able to invoke effective actions on (multi) selected elements.
What We Do Not Want This Project To Provide
View Content of File
Providing alternative visualization of content of a file has been requested
few times (
#10,
#11,
#25) and althrough it might easily
fall into one or two categories in previous section, it is kept separate as it
is more likely request for UI spec and reuse of navigator than something
to be handled directly by this display architecture.
What We Want To Provide To Our Developers
This section provides list of requirements gathered on the base of previous
section, with their priorites and ways to measure how well they are
implemented in various solutions.
Guidelines
| Id |
Description |
Priority |
How to Measure? |
| FindDoc |
The developers that will want to use the display technology
need to be able to find the correct documentation quickly.
|
|
The starting point is the NetBeans documentation page and it
is expected that the user is familiar with its structure (in order
to eliminate own problems of the documentation). Then the score
is the amount of time needed for the developer to find out solution
to a variation of one of the problems cited in
What Our Developers Say section.
|
| UnderstandDoc |
It shall be simple to understand what the documentation
describes, what actions shall be done and how to tailor
provided examples into own solution.
|
|
We shall have an API usablility study that will ask the
NetBeans 4.0 API experienced developers to expose contact like this
and consume contract defined by this display framework.
Their solution is going to be compared to sample one and
the less differences the better.
|
| DefineContract |
Offering other modules the visual extension point shall be
easy and as that also forms an exported api it shall be easy
to make such documentation visible to external developers.
|
|
The amount of non-code documents that are needed to get
description of the contract into javadoc and arch documents
shall be low compared to the code that needs to be written.
|
| PlugIn |
Enhancing new view of an existing module shall not be
complicated (after finding in docs that it is possible). The
amount of java and non-java code shall be of reasonable size.
|
|
Size of the unrelated code - for example the one that needs
to be written to change icon while not having anything to do with
icons - shall be as small as possible. The amount of non-java
code shall be small and error proof.
|
| TypeSafe |
Given the possible dynamic nature of the extensible visualization
framework it is desirable to minimize amount of type casting. This
will catch more problems during compile time and thus prevent
mistakes that otherwise might be found late or not at all.
|
|
Minimize the amount of typecasting when querying
a result, when extending new feature, listening on changes
and defining new visual extension point.
|
| Testability |
Applications written according to display architecture
guidelines need to be easily testable in a reliable way.
This means the behaviour shall be deterministic and setup
of unit test environement (which is usually the biggest
obsticle) shall be simple.
|
|
The less of additional libraries needed to setup the
environment the better. The more random test failure caused
by the infrastructure, the worse.
|
Visualization In Standard Views
| Id |
Description |
Priority |
How to Measure? |
| PlugInView |
The complexity of starting to use new display framework
inside of existing (node based) view shall be low. It is
unreasonable to expect that we manage to migrate all of
our (and partner) modules to new display infrastructure.
That is why it is more wise to provide incremental migration
path - e.g. allow also local switch to new display framework
that will work in existing views and end user will not notice
difference.
|
|
How much code is needed (if that is even possible) to accomodate
new display architecture for one node (either
node in runtime tab, favorites, projects or files view) into
existing views. The less, the better.
|
| CreateOwnView |
Creation of a visual component showing some objects
using the display architecture is natural starting point
for newly written modules and as such shall be easy.
|
|
The amount of code to create a tree view that is fully integrated
into the rest NetBeans framework. Actions has to work (like
Save), global property sheet update itself and navigator
content is updated as expected.
|
| StrategyFirst |
The solution supports selection of first answer from many.
This is needed for simple cooperation over selection of
name, icon, behaviour of open action, etc.
|
|
How much code is needed to write a view that will select
one display name for an object if more is provided.
|
| StrategyCompound |
The solution supports merging of answers together.
This is usually useful for composition of multiple child
objects for an element or for composition of popup menu.
|
|
How easy is to write a view that composes actions or
children or properties from all suggested ones.
|
| StrategyReordering |
The solution supports reorder of merged answers. This is
another level of StrategyCompound as it supports
additional coopearation on order which may be desirable for
achieving more pleasant end user experience (for example in
case of order of actions in menu).
|
|
Can the compound answers be reordered somehow? Is it possible
to reorder them by groups only or one by one. Does the pieces
providers need to know about each other or not?
|
| StrategyCustom |
Support for own special strategy. Sometimes
a producer of a contract would like to define its own
way to create the final result from more provided.
|
|
How much control a provider of the view can gain on the
merge of the componoud results? Is the code simple?
|
| StrategyBadging |
Special support for bagging.
Bagging of icons and to certain extent names
is currently used in many places in our explorer
and as it is a complex example of merge strategy, it makes
sence to ask whether the solution guides or even helps the
modules writers to simply achieve what they need.
|
|
How complex is the code to allow badging of images (or strings)
between multiple providers? The simpler the better. Does it
support any composition or just a fixed pattern? The more
freedom, the better.
|
Invite Participants
| Id |
Description |
Priority |
How to Measure? |
| MultiRegs |
More registration points for the same type of object.
The same object often needs different visualization even
it the same view - for example children of a class (e.g. methods
and fields) can be
different when one wants to see internal implementation details
or just public interface.
|
|
How complex is to define a registration point? The less code
and the better.
Any differences (performance, ease-of-use, etc.)
between the first one and the next? Zero differences would be the
best.
|
| DeclarativeRegs |
Support for declarative registration. It is possible to imagine
java api based on method calls to perform registation, but that
would probably lead to a lot of code execution on startup as
each module would need to run their initialization and increase
the starupt time. On the other hand declarative registration can
be processed once and then read only on demand.
|
|
The amount of code needs to run on initialization of the system
or of the view to register the display framework extensions.
The less the better.
|
| BestFit |
Possibliity to define own bestfit strategy.
Sometimes the selection of the most suitable viewer cannot
fit into any predefined rules (like in case of XML document -
#23) and then the provider of the contract would welcome
a chance to step in and select the best according to his
computation.
|
|
How much complex (if even possible) it is to define own
best fit strategy?
|
| Clasification |
Possibility to participate as a provider of a feature based
on some object's clasification. Imagine someone willing to
add an action to any element represeting file, someone else
only to xml files, someone else only to files in project tab.
Each of this represent different criteria of the element and
based on its presence triggers actual contributors.
|
|
Is clasification on more than one criteria supported?
More than one criteria is better.
How much lines takes to define such clasification? Has the
clasification be anticipated by the creator of the view or
can external modules add new clasifications? The later is
better. What is the performance of the selection of
applicable clasifications? The ratio of asked providers vs.
finally used providers shall be close to one.
|
| CompileTypeCheck |
Build time check that a registration is correct. Our experience
shows that debugging wrong declarative registrations is pretty
tedious task, which can be prevented by pre-runtime test of
correctness of such declarations.
|
|
How much mistakes in registrations (type problems, typos, etc.)
` can be caught during build time. The more the better.
How much additional tools
(over javac) is needed. Plain javac would be optimal.
|
Extensible Contract
| Id |
Description |
Priority |
How to Measure? |
| NewContract |
Allow two end sides to define new contract. This is needed
as from time to time people come up with new ideas how one
side (view) can do more fancy things and if the other side
(providers) suply some information. In these cases the
display architecture should not stay in a way and should allow
definition of new contract.
|
|
How complex is it (if even possible) to add new contract
(html display name, name abbrevations, scrollbar policy, etc.)
between consumer (the view) and provider (the registered
providers)? The less code the better. The less possiblity
to break older contracts the better.
|
| NewAsOld |
The nealy defined contract shall be similar to build-in ones.
Certain existing solution provided the extensiblity, but
the new defined contracts looked differently to API users and
may not perform as well as the old ones.
|
|
Can one see difference between new contract and build-in one?
Does it behave differently in terms of API or performance?
Bad if it is different even worse if it is not as good.
|
| TypeSafeExt |
New contracts shall be well typed. As there will be more
new contracts as build-in ones, they shall meet the criteria
of type safety for the sakes of compile time error checks.
|
|
How much casts is it needed to add and use new contract?
Probably not less then in case of build-in one, but any
additional casts are bad.
|
| RuntimeExt |
Runtime discovery of extra capabilities. Certain parts
of code need to find out contracts supported by an element
during runtime - this is especially useful for apisupport
bean browse tool which is very handy for any module
writer trying to understand what a certain visual element
provides.
|
|
Can the code discover all the extra capabilities during
runtime? The more the better.
|
| APIvsSPI |
Separation of API and SPI. It has been experienced that
as soon as the same api starts to be used for calls as well
as implementation, its evolution gets pretty complicated and
even possible it is unlikely to reach full compatibility.
|
|
Is there an interface that would prevent or complicate future
evolution and improvements to the framework? The more of such
interfaces the worse.
|
| MoreImpls |
More implementations of the providers. Requirements will change
and one day the best approach to address them can be to leave
to previous registration mechanisms and switch to completely
new one, while preserving the extension points. For that
support for multiple implementations fo the same api is going
to be benefitial.
|
|
Is the implementation closed or can external modules
enhance registration, delegation, implementation of the
same API? Openess is better.
Can there by multiple ways to implement the
same api contract? More ways, is better.
Is this invisible from the client point of view?
Invisibility is good.
|
Lifecycle
| Id |
Description |
Priority |
How to Measure? |
| Listeners |
Solution provides listener support. Standard way of listening
on changes in displayed objects is essential for most of usages.
|
|
How easy is to listen on change of certain aspect of an object?
The less code, the better.
Can multichanges be delivered in groups, so repaints are
optimized?
Optimization of repaints is good thing.
Do listeners register only when needed and unregister
when no longer needed?
The less wasted memory and listener storms, the better.
|
| Memory |
Little overhead in memory. The architecture has to occupy
some additional memory in order to observe the displayed
elements, howeve this shall be optimized.
|
|
The lower over head over the original object the better.
This shall include the caches, listeners, in case of
multiple providers of an aspect as well as objects with or
without beans support.
|
| MultiOps |
The support for multi selection operations. Sometimes
in current NetBeans one cannot easily group multioperations
which in turn results in bad UI perception (blinking display)
and slower performance (repaint needed after every operation
or more connections to server, etc.).
|
|
Can an action be invoked on multi selection of objects?
Good if it can.
How complex is to write such action?
The optimal is no difference in action for single
and multiple objects (exception iteration).
Is there support for
group operations - e.g. the repaint happens only after the
the whole operation is finished?
Good if there is.
|
| Threading |
Solution defines threading model. Knowing the model can
simplify life of callers and well as implementators of
registered extensions.
|
|
Is the threading defined?
Definition is a must.
Is it enforced?
Enforcing is good.
Is it implementable? Well, it should be.
Does it define listener firing model?
Well it should.
Is it deterministic and testable?
Testability is a must.
|
| SlowPlugins |
Support for slow plugins. It is clear that as soon as one
allows others to plug-in, the performance gets compromised.
Well defined architecture shall get ready for not optimally
written plugins.
|
|
Does it deal with "slow" plugin
response times?
Ability to satisfy percieved performance guidelines even if
plugins do not comply is a plus.
Are there multiple choices - e.g. slow and
fast mode?
If a fast model cannot be presented to user as really fast
(for example the repaint gets done later than it could), then it is
a huge minus.
Can one invoke any API in fast (AWT) and slow (other
code) mode?
Better if possible, as it allows simpler code in some cases.
|
Send comments and patches to
nbdev@netbeans.org.