This is a small part of our focus/validation framework.
I just try to explain it as simple as possible.

javax.swing.InputVerifier gives only access to the source component.

We need to know the target component.

Would it be possible to overload verify(..) (or introduce another method) which has the "to"/target component as a argument too?

Thanks
Reto Merz


On 14.04.2016 16:52, Semyon Sadetsky wrote:
Thank for explanation.
It seems to me such functionality belongs to the input validation domain
and should not be mixed up with the Swing focus transfer internals.
Swing has javax.swing.InputVerifier which you could extend and set to
each component of your framework. I suppose it would be better design
choice for you because it decouples your code from the focus transfer
details which may be changed in future JDK releases. While the
javax.swing.InputVerifier functionality will be preserved.

--Semyon

On 4/14/2016 4:58 PM, Reto Merz wrote:
Exactly, the target can reject the focus transfer (and the source too).
All our UI components support "FocusRequestEnterExit" listeners
which has a requestEnter(EnterExitEvent) and requestExit(EnterExitEvent) method 
(among others focusGained/focusLost methods).
The EnterExitEvent has a reject() and accept() method.

requestEnter is invoked on the target component and requestExit on the source 
component listeners.
The focus is only transferred after all source/target listeners have accept it.
This can be used for simple user input validation.

It is far more complex because our RIA is ULC based 
(https://ulc.canoo.com/developerzone/technicalconcept.html)
which split UI components into client- and server-side half objects,
but, basically this is how parts of our focus/validation framework works.

Open Component#requestFocusInWindow(CausedFocusEvent.Cause) does not work
because this allows only conditional invoking super.requestFocusInWindow.
At this point it is not yet clear if the focus can be really transferred (see 
isRequestFocusAccepted).
And after super.requestFocusInWindow it is to late because
KeyboardFocusManager.setMostRecentFocusOwner is already invoked.

 From my point of view the best (and easiest to maintain) solution is
introducing a isRequestFocusAccepted() method which is invoked
by isRequestFocusAccepted(boolean,boolean,CausedFocusEvent.Cause) at the end.
So the new isRequestFocusAccepted makes the final decision to transfer focus or 
not.
Furthermore that dont require to make CausedFocusEvent.Cause public (which 
looks a bit creepy).

Best Regards
Reto Merz

On 14/04/16 14:49, Semyon Sadetsky wrote:

Okay... You said the you need to intercept the focus request in the place
where the target is set.
  From my point of view opening
Component#requestFocusInWindow(CausedFocusEvent.Cause cause)
resolves that.
But it looks like you need extra. What is the final purpose? Maybe you want
to reject focus transfer depending on the target?

--Semyon

On 4/14/2016 3:19 PM, Reto Merz wrote:
Thanks for your investigation Semyon.

Make Component#requestFocusInWindow(CausedFocusEvent.Cause
cause) public/protected will not help us.
I can explain it more detailed if you want.

What would help is to introduce a "protected boolean
Component#isRequestFocusAccepted()"
which is invoked by

Component#isRequestFocusAccepted(boolean,boolean,CausedFocusEvent.
Caus
e) after the "Component.requestFocusController.acceptRequestFocus"
statement (and only if acceptRequestFocus has returned true).

This way you also don't have to make CausedFocusEvent.Cause public.

Best Regards
Reto Merz

On 14/04/16 13:09, Semyon Sadetsky wrote:

The FocusTraversalPolicy can be obtained using public API. It may give you
the target. But I believe this is not what you would like to do...
It seem sensible to make
Component#requestFocusInWindow(CausedFocusEvent.Cause cause)
public. Will it be enough for you?
I could start to implement this right after the 8080395 push.

--Semyon

On 4/14/2016 12:30 PM, Reto Merz wrote:
Hello Semyon,

We need to know the target component: "which component will be
focused".
Target component means the component which should be "really"
focused,
so this can only be known after all the FocusCycle / FocusTraversalPolicy
logic has processed.
DefaultKeyboardFocusManager
focusNextComponent/focusPreviousComponent
provides only the source component. Not the target.

The second argument of RequestFocusController#acceptRequestFocus is
the "real" target component.
We use only this argument in our custom RequestFocusController
implementation.
Thanks
Reto Merz

On 14/04/16 08:31, Semyon Sadetsky wrote:
Hi Reto,

It is unlikely that AWTAccessor API may be opened. It gives access to
internal undocumented methods not to even mention that those methods
have private and package accesses.
As I understand you need the way to intercept focus transfer initiated by a
traversal key. Why to subclass the DefaultKeyboardFocusManager to
override its focusNextComponent/ focusPreviousComponent methods?
--Semyon

On 4/12/2016 2:37 PM, Reto Merz wrote:
Hello Alexandr,

Basically we need to detect and intercept focus changes.

java.awt.Component allows to override this methods:
requestFocus()
requestFocus(boolean)
requestFocusInWindow()
requestFocusInWindow(boolean)

requestFocus() is only invoked when the component is focused by a mouse
click.
But no requestFocus* method is invoked when a FocusTraversalPolicy is
involed (f. e. the user press TAB to focus next component).

sun.awt.RequestFocusController#acceptRequestFocus is invoked in both
cases.
Attached a demo to reproduce it:
- if TextField is focused by a mouse click "requestFocus" and
"acceptRequestFocus" is logged
- if TextField is focused by TAB only "acceptRequestFocus" is logged

Some more notes about the test program:
ComponentAccessorDelegator delegates all calls to the original
ComponentAccessor implementation.
Only ComponentAccessor#setRequestFocusController is changed to keep
our RequestFocusController implementation.
I have just filled a RFE onhttp://bugreport.java.com/bugreport

Thanks
Reto Merz


On 11/04/16 21:02, Alexander Scherbatiy wrote:
   Hello Reto,

   Could you provide use cases which illustrate tasks the requested API is
intended to solve in your application?
   Please, also create a request in the bug system
http://bugreport.java.com/bugreport

   Thanks,
Alexandr.

On 11/04/16 12:26, Alexander Scherbatiy wrote:

   Resending the request to awt-dev alias.

   Thanks,
   Alexandr.

On 4/4/2016 4:54 PM, Reto Merz wrote:
Hello,

Jigsaw will disallow access to internal packages.
We have written a complex validation and focus management
implementation for our closed-source RIA and maintain it since JRE
1.4.

For this we use some internal API. We have a custom implementation of
these interfaces:

sun.awt.RequestFocusController
sun.awt.AWTAccessor.ComponentAccessor

And use this getter and setter:


sun.awt.AWTAccessor#setComponentAccessor(AWTAccessor.ComponentAc
cesso
r)
sun.awt.AWTAccessor#getComponentAccessor()

sun.awt.AWTAccessor.ComponentAccessor#setRequestFocusController(Req
ue
stFocusController)


Please make this API public.

Furthermore we need to call
java.awt.Component#revalidateSynchronously().
We do this with reflection. It would be nice to have a public API for
this.
Maybe a new static method on AWTAccessor:
AWTAccessor.revalidateSynchronously(Component)

Best Regards
Reto Merz









Reply via email to