-
Enhancement
-
Resolution: Unresolved
-
P4
-
8u192
-
x86_64
-
windows_10
ADDITIONAL SYSTEM INFORMATION :
Windows 10 Pro, 64 bit
A DESCRIPTION OF THE PROBLEM :
The current behavior in Swing is to hide the caret in a non-editable text
component. A previous bug entry proposed to change this, i.e. to only hide the
caret if the component is disabled:
JDK-4248316 : DefaultCaret.focusGained does not reactivate caret if editable false
(https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4248316).
This was rejected with the reason that the current behavior is as intended.
However, I am now proposing to make the behavior configurable, because we
would like to change it in our project for the following reasons:
1) An enabled component is focusable, but it's only through the caret and the
selection that the user understands whether a text component is focused or not.
When using the keyboard to navigate through multiple empty text components, it
is unclear which component is focused until you hit an editable one. You can try
this in the following example:
public static void main(String[] args) {
JFrame frame = new JFrame();
Container c = frame.getContentPane();
frame.setLayout(new BoxLayout(c, BoxLayout.PAGE_AXIS));
c.add(readonly(new JTextField(20)));
c.add(readonly(new JTextField(20)));
c.add(new JTextField(20));
c.add(readonly(new JTextField(20)));
c.add(readonly(new JTextField("Select 'this' using keyboard!", 20)));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
private static JTextField readonly(JTextField tf) {
tf.setEditable(false);
return tf;
}
2) It is easier to select text for copying it to the clipboard when a caret is
shown. For example, you can move the caret in a readonly text field using the
keyboard, but you don't see the caret's current position. To see this, try
selecting the string "this" from the last text field in the example above,
using the keyboard.
3) Other UI platforms also show a caret in readonly fields.
For example, readonly text fields in Windows 10 show a caret.
Similarly, Firefox and Internet Explorer show a caret when focusing the
following input field (whereas Chrome and Edge don't):
<input type="text" value="non-editable" readonly/>
Before posting this request, I was looking for an existing way to configure
this behavior. InJDK-4248316, it was mentioned that one can customize the
caret's behavior by plugging in a custom Caret implementation. I tried to do
that, but without success.
It seems that this should be done by creating a custom class that extends TextUI
and overrides createCaret(), and setting that class as the UI-class of the
corresponding component in the UIDefaults.
However, this must be done for every subclass of JTextComponent that overrides
JComponent.getUIClassID() (there are six in the JDK).
Moreover, some Look & Feels have their own TextUI and Caret implementations.
For example, in the Windows Look & Feel, there is the WindowsTextFieldUI class,
whose createCaret() method returns a WindowsFieldCaret. The WindowsFieldCaret
class overrides some protected methods, e.g. its getSelectionPainter() method
returns a WindowsTextUI.WindowsPainter. So, to change the caret's focus behavior
without changing anything else, one must subclass WindowsFieldCaret. But that's
not possible because this class is package-private. It's also not possible to
re-implement getSelectionPainter(), because WindowsTextUI.WindowPainter is
package-private, too.
Therefore, I propose to introduce some configuration mechanism, and to respect
that configuration in the DefaultCaret class, like:
public void focusGained(FocusEvent e) {
if (component.isEnabled()) {
if (alwaysShow || component.isEditable()) {
setVisible(true);
}
setSelectionVisible(true);
}
}
where alwaysShow would be a new field that stores the configured behavior.
There are several possibilities for configuring the behavior, including the
definition of a new system property, e.g.
"javax.swing.plaf.showCaretWhenNotEditable", or some runtime configuration
similar to the existing DefaultCaret.setUpdatePolicy().
From the above options, I would prefer the system property because it is easier
to configure globally, but any solution that allows global configuration is
fine.
If we agree on a solution, I can also implement it myself and submit a patch if
you like.
Windows 10 Pro, 64 bit
A DESCRIPTION OF THE PROBLEM :
The current behavior in Swing is to hide the caret in a non-editable text
component. A previous bug entry proposed to change this, i.e. to only hide the
caret if the component is disabled:
(https://bugs.java.com/bugdatabase/view_bug.do?bug_id=4248316).
This was rejected with the reason that the current behavior is as intended.
However, I am now proposing to make the behavior configurable, because we
would like to change it in our project for the following reasons:
1) An enabled component is focusable, but it's only through the caret and the
selection that the user understands whether a text component is focused or not.
When using the keyboard to navigate through multiple empty text components, it
is unclear which component is focused until you hit an editable one. You can try
this in the following example:
public static void main(String[] args) {
JFrame frame = new JFrame();
Container c = frame.getContentPane();
frame.setLayout(new BoxLayout(c, BoxLayout.PAGE_AXIS));
c.add(readonly(new JTextField(20)));
c.add(readonly(new JTextField(20)));
c.add(new JTextField(20));
c.add(readonly(new JTextField(20)));
c.add(readonly(new JTextField("Select 'this' using keyboard!", 20)));
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
private static JTextField readonly(JTextField tf) {
tf.setEditable(false);
return tf;
}
2) It is easier to select text for copying it to the clipboard when a caret is
shown. For example, you can move the caret in a readonly text field using the
keyboard, but you don't see the caret's current position. To see this, try
selecting the string "this" from the last text field in the example above,
using the keyboard.
3) Other UI platforms also show a caret in readonly fields.
For example, readonly text fields in Windows 10 show a caret.
Similarly, Firefox and Internet Explorer show a caret when focusing the
following input field (whereas Chrome and Edge don't):
<input type="text" value="non-editable" readonly/>
Before posting this request, I was looking for an existing way to configure
this behavior. In
caret's behavior by plugging in a custom Caret implementation. I tried to do
that, but without success.
It seems that this should be done by creating a custom class that extends TextUI
and overrides createCaret(), and setting that class as the UI-class of the
corresponding component in the UIDefaults.
However, this must be done for every subclass of JTextComponent that overrides
JComponent.getUIClassID() (there are six in the JDK).
Moreover, some Look & Feels have their own TextUI and Caret implementations.
For example, in the Windows Look & Feel, there is the WindowsTextFieldUI class,
whose createCaret() method returns a WindowsFieldCaret. The WindowsFieldCaret
class overrides some protected methods, e.g. its getSelectionPainter() method
returns a WindowsTextUI.WindowsPainter. So, to change the caret's focus behavior
without changing anything else, one must subclass WindowsFieldCaret. But that's
not possible because this class is package-private. It's also not possible to
re-implement getSelectionPainter(), because WindowsTextUI.WindowPainter is
package-private, too.
Therefore, I propose to introduce some configuration mechanism, and to respect
that configuration in the DefaultCaret class, like:
public void focusGained(FocusEvent e) {
if (component.isEnabled()) {
if (alwaysShow || component.isEditable()) {
setVisible(true);
}
setSelectionVisible(true);
}
}
where alwaysShow would be a new field that stores the configured behavior.
There are several possibilities for configuring the behavior, including the
definition of a new system property, e.g.
"javax.swing.plaf.showCaretWhenNotEditable", or some runtime configuration
similar to the existing DefaultCaret.setUpdatePolicy().
From the above options, I would prefer the system property because it is easier
to configure globally, but any solution that allows global configuration is
fine.
If we agree on a solution, I can also implement it myself and submit a patch if
you like.
- relates to
-
JDK-4248316 DefaultCaret.focusGained does not reactivate caret if editable false
-
- Closed
-