[openide-dev] Node mouse events

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

[openide-dev] Node mouse events

agage
Quick question, for which the answer is probably "no -- that would be a
usability nightmare".

I have extended BeanTreeView to use a custom NodeRenderer.  This custom
renderer gets a VisualizerNode, grabs the original node from there, and
looks for an interface that provides a Component.  If it finds it, then the
Component is what is drawn for that Node.

That much works fine.

However, any controls that I put into the component never get any mouse
events.  The Node is trapping all of them for selection and expansion.

I'm basically trying to put shuttle controls (play, pause, rewind,
go-to-index) in the tree view to provide an unambiguous way of managing the
parent of the controls.  Dialog boxes for each would become unwieldy (since
there could be a dozen open and playing back at once).  And while I could
use actions for some of these (play, pause, change direction), jumping to a
particular index would require opening a separate dialog.  I'd prefer to
just give them a slider and spinners, plus buttons for the simple controls,
most of which can be hidden to save space.

Is there any hope of making this work?  Or would I be better off doing
something else (like creating another TopComponent in the same mode that
provides these controls but not with Nodes)?

Any suggestions welcome.  Thanks.

===
Dr. Aaron Gage ([hidden email])
Software Development for Ocean Optics, Inc.
http://www.OceanOptics.com

Reply | Threaded
Open this post in threaded view
|

[openide-dev] Re: Node mouse events

Tim Boudreau
aaron.gage wrote:
> Quick question, for which the answer is probably "no -- that would be a
> usability nightmare".
>
> I have extended BeanTreeView to use a custom NodeRenderer.  This custom
> renderer gets a VisualizerNode, grabs the original node from there, and
> looks for an interface that provides a Component.  If it finds it, then the
> Component is what is drawn for that Node.

Ack!  Unless you're *very* careful, be prepared for performance
problems.  A few hints:

  - Try to reuse one component for as many nodes as possible
  - Make sure you override validate, repaint, etc. to be no-ops - just
do the same things DefaultTreeCellRenderer does
  - Embedded JLabels in particular can benefit from making
firePropertyChange (String, Object, Object) a no-op, so the LabelUI
doesn't do a relatively expensive check to see if the string is HTML

> That much works fine.
>
> However, any controls that I put into the component never get any mouse
> events.  The Node is trapping all of them for selection and expansion.

That will never work, not due to any NetBeans bug, but due to the nature
of Swing trees.  Your components aren't really "there" - the painting
infrastructure for a tree just takes a component (usually the same
component is reused for every cell) and uses it like a rubber stamp -
configure it, paint with it, throw it away.

Swing trees do this by getting the cell editor, adding it to an
offscreen CellRendererPane (basically a component that fools its child
components into thinking they're onscreen when they're not), telling it
to paint itself into the rectangle for the tree node, then repeating the
process for the next node, until it's run out of visible nodes to paint.
  Your components are never actually in the real component hierarchy you
see on screen.

The best you could possibly do is use instances of the same component
for the tree cell *editor* and the renderer (but do not use the same
component instance for both, or your editor will be suddenly evaporate
when the tree needs to paint), have your tree go into edit mode on a
single click, and forward the mouse event that initiated the edit to the
now-visible editor.

> I'm basically trying to put shuttle controls (play, pause, rewind,
> go-to-index) in the tree view to provide an unambiguous way of managing the
> parent of the controls.  Dialog boxes for each would become unwieldy (since
> there could be a dozen open and playing back at once).  And while I could
> use actions for some of these (play, pause, change direction), jumping to a
> particular index would require opening a separate dialog.  I'd prefer to
> just give them a slider and spinners, plus buttons for the simple controls,
> most of which can be hidden to save space.

Interesting problem.

It was in interesting enough problem that I wrote half this email, then
took a few minutes and prototyped what I'm suggesting you do, to make
sure it would work.  I'll send it to you privately to give you an idea
of how this can be made to work.

You can do it with a JTree;  I don't know that BeanTreeView gives enough
access to the underlying tree to do it with nodes, but it's definitely
doable with a JTree - the click that puts the tree into edit mode will
be forwarded to the component inside the editor, so you can do single
click editing.  Note that handling tooltips requires a bit of special
fiddling.

Note there are some hard problems there - keyboard behavior will be ill
defined (presumably pressing space or something should put the selected
cell into edit mode, but you'll need to visually indicate that).  Also,
focus behavior may be strange - where focus goes when the focused
component is removed from the screen tends to be pretty random;  and
after you click a button (putting the tree into edit mode
transparently), the button that gets focus will be the first one, not
the one that was clicked unless you do some special fiddling with, say,
a FocusTraversalPolicy to make sure the default component to focus is
whatever was clicked last.

-Tim