Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions CodenameOne/src/com/codename1/ui/TextArea.java
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ public class TextArea extends Component implements ActionSource, TextHolder {
private final EventDispatcher listeners = new EventDispatcher();
private ActionListener doneListener;
private int valign = defaultValign;
/// True once setVerticalAlignment() has been called, so the multi-line TOP
/// default in getVerticalAlignment() no longer overrides an explicit choice.
private boolean verticalAlignmentSet;
private int linesToScroll = 1;
//private int modifierFlag = 0x00000;
/// Unsupported characters is a string that contains characters that cause issues
Expand Down Expand Up @@ -1380,6 +1383,15 @@ void paintHint(Graphics g) {
if (Display.getInstance().isNativeEditorVisible(this) && Display.impl.nativeEditorPaintsHint()) {
return;
}
// For multi-row text areas, keep the hint vertically aligned with where
// the text will actually be rendered/edited so it doesn't sit in the
// middle while the cursor is on the first line (issue #5345). Single-line
// fields and one-row growable fields (e.g. a chat input) keep their
// existing (centered) hint behavior since there is no meaningful gap.
Label hint = getHintLabelImpl();
if (hint != null && !isSingleLineTextArea() && getActualRows() > 1) {
hint.setVerticalAlignment(getVerticalAlignment());
}
super.paintHint(g);
}

Expand Down Expand Up @@ -1852,11 +1864,16 @@ boolean shouldShowHint() {
return "".equals(getText());
}

/// Returns the vertical alignment of the text field.
/// Returns the vertical alignment of the text field, one of: CENTER, TOP, BOTTOM
///
/// For multi-line text areas, this alignment is applied only while there is extra
/// vertical space in the component. If the text content uses all available height
/// (or overflows), the rendering naturally starts from the top.
/// Multi-line text areas default to #TOP, regardless of the theme default
/// (`textCmpVAlignInt`, which is meant for single-line fields). Single-line fields
/// keep the theme default. A value passed to #setVerticalAlignment(int) is always
/// honored as-is, so an explicit #CENTER / #BOTTOM still works (e.g. for display
/// text). For editable multi-line areas the #TOP default also keeps the lightweight
/// rendering aligned with the native editor, which top-aligns its content on every
/// current platform, so the text, cursor and hint don't jump when editing starts
/// and ends (issue #5345).
///
/// #### Returns
///
Expand All @@ -1870,6 +1887,9 @@ boolean shouldShowHint() {
///
/// - #BOTTOM
public int getVerticalAlignment() {
if (!verticalAlignmentSet && !isSingleLineTextArea()) {
return TOP;
}
return valign;
}

Expand All @@ -1879,6 +1899,11 @@ public int getVerticalAlignment() {
/// vertical space in the component. If there is no extra room, alignment becomes
/// effectively top-aligned because content already fills the available area.
///
/// Setting a value here overrides the multi-line #TOP default described in
/// #getVerticalAlignment(): the value you pass is honored even for an editable
/// multi-line area (which may then visibly shift when its native editor, which
/// top-aligns, takes over).
///
/// #### Parameters
///
/// - `valign`: alignment value
Expand All @@ -1895,6 +1920,7 @@ public void setVerticalAlignment(int valign) {
throw new IllegalArgumentException("Alignment can't be set to " + valign);
}
this.valign = valign;
this.verticalAlignmentSet = true;
}

/// {@inheritDoc}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,63 @@ void testVerticalAlignmentRejectsInvalidValues() {
assertThrows(IllegalArgumentException.class, () -> textArea.setVerticalAlignment(Component.BASELINE));
}

@FormTest
void testMultilineDefaultsToTop() {
// Regression test for #5345: with a CENTER theme default a multi-line text
// area reports TOP by default (the theme default is meant for single-line
// fields). For an editable area this matches the top-aligning native editor,
// so the text doesn't jump when editing starts and ends.
int previous = TextArea.getDefaultValign();
TextArea.setDefaultValign(Component.CENTER);
try {
TextArea editable = new TextArea("text text", 3, 20);
editable.setEditable(true);
assertEquals(Component.TOP, editable.getVerticalAlignment());

TextArea nonEditable = new TextArea("text text", 3, 20);
nonEditable.setEditable(false);
assertEquals(Component.TOP, nonEditable.getVerticalAlignment());
} finally {
TextArea.setDefaultValign(previous);
}
}

@FormTest
void testExplicitVerticalAlignmentOverridesMultilineDefault() {
// An explicit setVerticalAlignment() is honored even for a multi-line area,
// so display text can still be centered/bottom-aligned.
int previous = TextArea.getDefaultValign();
TextArea.setDefaultValign(Component.CENTER);
try {
TextArea textArea = new TextArea("text text", 3, 20);
textArea.setEditable(false);

textArea.setVerticalAlignment(Component.CENTER);
assertEquals(Component.CENTER, textArea.getVerticalAlignment());

textArea.setVerticalAlignment(Component.BOTTOM);
assertEquals(Component.BOTTOM, textArea.getVerticalAlignment());
} finally {
TextArea.setDefaultValign(previous);
}
}

@FormTest
void testSingleLineKeepsThemeVerticalAlignment() {
// Single-line fields keep the theme default (they center vertically in their
// native editor).
int previous = TextArea.getDefaultValign();
TextArea.setDefaultValign(Component.CENTER);
try {
TextArea textArea = new TextArea("text", 1, 20);
textArea.setSingleLineTextArea(true);
textArea.setEditable(true);
assertEquals(Component.CENTER, textArea.getVerticalAlignment());
} finally {
TextArea.setDefaultValign(previous);
}
}

@FormTest
void testVerticalAlignmentScreenshotStates() {
Form form = new Form("TextArea VAlign", BoxLayout.y());
Expand Down
Binary file modified scripts/ios/screenshots-metal/ButtonTheme_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/ButtonTheme_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/ChatView_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/ChatView_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/DialogTheme_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/DialogTheme_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/ShowcaseTheme_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/ShowcaseTheme_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/SpanLabelTheme_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/SpanLabelTheme_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/SwitchTheme_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/SwitchTheme_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/TextFieldTheme_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-metal/TextFieldTheme_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-tv/ChatView_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-tv/ChatView_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-tv/SpanLabelTheme_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-tv/SpanLabelTheme_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-watch/AppReviewDialog.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-watch/ChatView_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-watch/ChatView_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-watch/DialogTheme_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-watch/DialogTheme_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-watch/SpanLabelTheme_dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots-watch/SpanLabelTheme_light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified scripts/ios/screenshots/ButtonTheme_dark.png
Binary file modified scripts/ios/screenshots/ButtonTheme_light.png
Binary file modified scripts/ios/screenshots/ChatView_dark.png
Binary file modified scripts/ios/screenshots/ChatView_light.png
Binary file modified scripts/ios/screenshots/DialogTheme_dark.png
Binary file modified scripts/ios/screenshots/DialogTheme_light.png
Binary file modified scripts/ios/screenshots/ShowcaseTheme_dark.png
Binary file modified scripts/ios/screenshots/ShowcaseTheme_light.png
Binary file modified scripts/ios/screenshots/SpanLabelTheme_dark.png
Binary file modified scripts/ios/screenshots/SpanLabelTheme_light.png
Binary file modified scripts/ios/screenshots/TextFieldTheme_dark.png
Binary file modified scripts/ios/screenshots/TextFieldTheme_light.png
Binary file modified scripts/mac-native/screenshots/ButtonTheme_dark.png
Binary file modified scripts/mac-native/screenshots/ButtonTheme_light.png
Binary file modified scripts/mac-native/screenshots/ChatView_dark.png
Binary file modified scripts/mac-native/screenshots/ChatView_light.png
Binary file modified scripts/mac-native/screenshots/DialogTheme_dark.png
Binary file modified scripts/mac-native/screenshots/DialogTheme_light.png
Binary file modified scripts/mac-native/screenshots/ShowcaseTheme_dark.png
Binary file modified scripts/mac-native/screenshots/ShowcaseTheme_light.png
Binary file modified scripts/mac-native/screenshots/SpanLabelTheme_dark.png
Binary file modified scripts/mac-native/screenshots/SpanLabelTheme_light.png
Binary file modified scripts/mac-native/screenshots/SwitchTheme_dark.png
Binary file modified scripts/mac-native/screenshots/SwitchTheme_light.png
Binary file modified scripts/mac-native/screenshots/TextFieldTheme_dark.png
Binary file modified scripts/mac-native/screenshots/TextFieldTheme_light.png
Loading