That sounds good.

Thanks for you efforts.

Best Regards
Reto Merz


On 4/14/2016 22:11, Semyon Sadetsky wrote:
> On 4/14/2016 9:25 PM, Reto Merz wrote:
>
> 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? 

Yes. That is what I will be able to do. Something like:

   public boolean verifyTarget(JComponent input) {
      return true;
  }

  public boolean shouldYieldFocus(JComponent from, JComponent to) {
    return shouldYieldFocus(from) && verifyTarget(to);
  }

--Semyon

> 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