<AWT Dev> <Swing Dev> Public RequestFocusController/AWTAccessor API
Semyon Sadetsky
semyon.sadetsky at oracle.com
Thu Apr 14 20:10:47 UTC 2016
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
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>
>>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.openjdk.java.net/pipermail/awt-dev/attachments/20160414/438b82e6/attachment-0001.html>
More information about the awt-dev
mailing list